/**
 @file sys_tmg_serdes.c

 @author  Copyright (C) 2023 Centec Networks Inc.  All rights reserved.

 @date 2023-02-10

 @version v1.0

*/
/****************************************************************************
 *
* Header Files
*
****************************************************************************/

#include "sys_usw_chip.h"
#include "sys_usw_dmps.h"
#include "sys_usw_datapath.h"
#include "sal.h"
#include "ctc_port.h"
#include "ctc_error.h"
#include "ctc_debug.h"
#include "ctc_interrupt.h"
#include "ctc_warmboot.h"
#include "drv_api.h"
#include "usw/include/drv_common.h"
#include "sys_usw_dmps_drv_def.h"
#include "sys_tmg_datapath.h"
#include "sys_usw_dmps_db.h"
#include "sys_tmg_mac.h"
#include "sys_usw_common.h"
#include "sys_tmg_serdes_fw.inc"
#include "sys_tmg_serdes.h"

#include "sys_usw_peri.h"
#include "sys_usw_stats_api.h"
#include "sys_usw_dmps.h"
#include "sys_usw_interrupt.h"
#include "sys_usw_port.h"
#include "sys_usw_mac.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_mcu.h"
#include "sys_usw_register.h"

#include "drv_api.h"
#include "usw/include/drv_common.h"
#include "sys_usw_register.h"
#include "usw/include/sys/sys_usw_serdes_api.h"

uint8 g_sram_bootloader_bypass = 1;

extern sal_file_t g_tm_dump_fp;
extern uint8 g_dmps_dbg_sw;
extern const sys_tmg_dmps_id_dictionary_s g_dmps_map_tmg[SYS_TMG_MAX_SERDES_NUM];
uint8 g_print_tbl;

int32 _sys_tmg_serdes_get_signal_detect(uint8 lchip, uint16 serdes_id, uint8* p_is_detect, uint8* p_raw_sigdet);
int32 _sys_tmg_serdes_set_lane_req(uint8 lchip, uint16 serdes_id, uint8 dir, uint32 enable);
int32 _sys_tmg_serdes_poll_lane_ack(uint8 lchip, uint16 serdes_id, uint8 dir, uint32 exp_value);
int32 _sys_tmg_serdes_set_lane_req(uint8 lchip, uint16 serdes_id, uint8 dir, uint32 enable);
int32 _sys_tmg_serdes_poweron_per_hss(uint8 lchip, uint16 hss_id);
int32 _sys_tmg_serdes_poweron_per_lane(uint8 lchip, uint16 serdes_id);
int32 _sys_tmg_serdes_poweron_per_macro(uint8 lchip, uint16 macro_id);
int32 _sys_tmg_serdes_clear_anlt_intr(uint8 lchip, uint16 serdes_id);
uint8 _sys_tmg_serdes_map_serdes_mode_to_pcs_type_sel(uint16 serdes_mode);
extern int32 _sys_usw_port_api_set_serdes_mode(uint8 lchip, ctc_chip_serdes_info_t* p_serdes_info);
extern int32 sys_tmg_datapath_lane_swap_cfg(uint8 lchip, uint16 hss_id, uint8 enable);
extern int32 _sys_tmg_datapath_get_lport_chan_by_serdes(uint8 lchip, uint16 logic_serdes, uint16* p_chan, uint16* p_dport);
extern uint32 _sys_tmg_datapath_get_serdes_support_speed_bmp(uint8 lchip, uint16 logical_serdes);

#if 1
#define DRV_IOW_FIELD_NZ(lchip, memid, fieldid, value, ptr, inst, index) \
         do\
         {\
             int retv = 0;\
             char   fld_str[64] = {0};\
             retv = drv_set_field(lchip, memid, fieldid, ptr, value);\
             if (retv < 0)\
             {\
                 return(retv); \
             }\
             drv_usw_get_field_string_by_id(lchip, memid, fieldid, fld_str);\
             if ((NULL != g_tm_dump_fp) && (g_dmps_dbg_sw)) \
             {\
                 sal_fprintf(g_tm_dump_fp, "//write chip 0 tbl-reg  %s.%d  %d  field %s %d\n", \
                     TABLE_NAME(lchip, memid), inst, index, fld_str, *value); \
                 sal_fflush(g_tm_dump_fp);\
             }\
         }\
         while(0)
#else

#define DRV_IOW_FIELD_NZ(lchip, memid, fieldid, value, ptr, inst) \
    do\
    {\
        int retv = 0;\
        char   fld_str[64] = {0};\
        retv = drv_set_field(lchip, memid, fieldid, ptr, value);\
        if (retv < 0)\
        {\
            return(retv); \
        }\
        drv_usw_get_field_string_by_id(lchip, memid, fieldid, fld_str);\
        sal_printf("// #write %-20s 0 inst %-5d entry 0 field %-20s 0x%x\n", \
                TABLE_NAME(lchip, memid), inst, fld_str, *value); \
    }\
    while(0)
#endif

#define DP_DEBUG_FUNCTION_CALLED_PRINT() \
            do \
            { \
                if ((NULL != g_tm_dump_fp) && (g_dmps_dbg_sw)) \
                {\
                    sal_fprintf(g_tm_dump_fp, "//------ %s enter ----------------\n", __func__); \
                }\
            } \
            while(0)

#define DP_DEBUG_FUNCTION_RETURN_PRINT() \
            do \
            { \
                if ((NULL != g_tm_dump_fp) && (g_dmps_dbg_sw)) \
                {\
                    sal_fprintf(g_tm_dump_fp, "//------ %s return ----------------\n", __func__); \
                }\
            } \
            while(0)

sys_tmg_serdes_temp_soft_table_t tmg_temp_soft_table[] =
{
    {TRUE,  SERDES_SPEED_25_78125G}, // 0
    {TRUE,  SERDES_SPEED_25_78125G}, // 1
    {TRUE,  SERDES_SPEED_25_78125G}, // 2
    {TRUE,  SERDES_SPEED_25_78125G}, // 3
    {TRUE,  SERDES_SPEED_25_78125G}, // 4
    {TRUE,  SERDES_SPEED_25_78125G}, // 5
    {TRUE,  SERDES_SPEED_25_78125G}, // 6
    {TRUE,  SERDES_SPEED_25_78125G}, // 7
    {FALSE,  SERDES_SPEED_25_78125G}, // 8
    {FALSE,  SERDES_SPEED_25_78125G}, // 9
    {FALSE,  SERDES_SPEED_25_78125G}, // 10
    {FALSE,  SERDES_SPEED_25_78125G}, // 11
    {FALSE,  SERDES_SPEED_25_78125G}, // 12
    {FALSE,  SERDES_SPEED_25_78125G}, // 13
    {FALSE,  SERDES_SPEED_25_78125G}, // 14
    {FALSE,  SERDES_SPEED_25_78125G}, // 15
    {FALSE,  SERDES_SPEED_25_78125G}, // 16
    {FALSE,  SERDES_SPEED_25_78125G}, // 17
    {FALSE,  SERDES_SPEED_25_78125G}, // 18
    {FALSE,  SERDES_SPEED_25_78125G}, // 19
    {FALSE,  SERDES_SPEED_25_78125G}, // 20
    {FALSE,  SERDES_SPEED_25_78125G}, // 21
    {FALSE,  SERDES_SPEED_25_78125G}, // 22
    {FALSE,  SERDES_SPEED_25_78125G}, // 23
    {FALSE,  SERDES_SPEED_25_78125G}, // 24
    {FALSE,  SERDES_SPEED_25_78125G}, // 25
    {FALSE,  SERDES_SPEED_25_78125G}, // 26
    {FALSE,  SERDES_SPEED_25_78125G}, // 27
    {FALSE,  SERDES_SPEED_25_78125G}, // 28
    {FALSE,  SERDES_SPEED_25_78125G}, // 29
    {FALSE,  SERDES_SPEED_25_78125G}, // 30
    {FALSE,  SERDES_SPEED_25_78125G}, // 31
};

sys_tmg_serdes_temp_soft_table_t tmg_temp_soft_table_3_125g[] =
{
    {TRUE,  SERDES_SPEED_3_125G}, // 0
    {TRUE,  SERDES_SPEED_3_125G}, // 1
    {TRUE,  SERDES_SPEED_3_125G}, // 2
    {TRUE,  SERDES_SPEED_3_125G}, // 3
    {TRUE,  SERDES_SPEED_3_125G}, // 4
    {TRUE,  SERDES_SPEED_3_125G}, // 5
    {TRUE,  SERDES_SPEED_3_125G}, // 6
    {TRUE,  SERDES_SPEED_3_125G}, // 7
    {FALSE, SERDES_SPEED_3_125G}, // 8
    {FALSE, SERDES_SPEED_3_125G}, // 9
    {FALSE, SERDES_SPEED_3_125G}, // 10
    {FALSE, SERDES_SPEED_3_125G}, // 11
    {FALSE, SERDES_SPEED_3_125G}, // 12
    {FALSE, SERDES_SPEED_3_125G}, // 13
    {FALSE, SERDES_SPEED_3_125G}, // 14
    {FALSE, SERDES_SPEED_3_125G}, // 15
    {FALSE, SERDES_SPEED_3_125G}, // 16
    {FALSE, SERDES_SPEED_3_125G}, // 17
    {FALSE, SERDES_SPEED_3_125G}, // 18
    {FALSE, SERDES_SPEED_3_125G}, // 19
    {FALSE, SERDES_SPEED_3_125G}, // 20
    {FALSE, SERDES_SPEED_3_125G}, // 21
    {FALSE, SERDES_SPEED_3_125G}, // 22
    {FALSE, SERDES_SPEED_3_125G}, // 23
    {FALSE, SERDES_SPEED_3_125G}, // 24
    {FALSE, SERDES_SPEED_3_125G}, // 25
    {FALSE, SERDES_SPEED_3_125G}, // 26
    {FALSE, SERDES_SPEED_3_125G}, // 27
    {FALSE, SERDES_SPEED_3_125G}, // 28
    {FALSE, SERDES_SPEED_3_125G}, // 29
    {FALSE, SERDES_SPEED_3_125G}, // 30
    {FALSE, SERDES_SPEED_3_125G}, // 31
};

sys_tmg_serdes_temp_soft_table_t tmg_temp_soft_table_1g[] =
{
    {TRUE,  SERDES_SPEED_1_25G}, // 0
    {TRUE,  SERDES_SPEED_1_25G}, // 1
    {TRUE,  SERDES_SPEED_1_25G}, // 2
    {TRUE,  SERDES_SPEED_1_25G}, // 3
    {TRUE,  SERDES_SPEED_1_25G}, // 4
    {TRUE,  SERDES_SPEED_1_25G}, // 5
    {TRUE,  SERDES_SPEED_1_25G}, // 6
    {TRUE,  SERDES_SPEED_1_25G}, // 7
    {FALSE,  SERDES_SPEED_1_25G}, // 8
    {FALSE,  SERDES_SPEED_1_25G}, // 9
    {FALSE,  SERDES_SPEED_1_25G}, // 10
    {FALSE,  SERDES_SPEED_1_25G}, // 11
    {FALSE,  SERDES_SPEED_1_25G}, // 12
    {FALSE,  SERDES_SPEED_1_25G}, // 13
    {FALSE,  SERDES_SPEED_1_25G}, // 14
    {FALSE,  SERDES_SPEED_1_25G}, // 15
    {FALSE,   SERDES_SPEED_1_25G}, // 16
    {FALSE,   SERDES_SPEED_1_25G}, // 17
    {FALSE,   SERDES_SPEED_1_25G}, // 18
    {FALSE,   SERDES_SPEED_1_25G}, // 19
    {FALSE,   SERDES_SPEED_1_25G}, // 20
    {FALSE,   SERDES_SPEED_1_25G}, // 21
    {FALSE,   SERDES_SPEED_1_25G}, // 22
    {FALSE,   SERDES_SPEED_1_25G}, // 23
    {FALSE,  SERDES_SPEED_1_25G}, // 24
    {FALSE,  SERDES_SPEED_1_25G}, // 25
    {FALSE,  SERDES_SPEED_1_25G}, // 26
    {FALSE,  SERDES_SPEED_1_25G}, // 27
    {FALSE,  SERDES_SPEED_1_25G}, // 28
    {FALSE,  SERDES_SPEED_1_25G}, // 29
    {FALSE,  SERDES_SPEED_1_25G}, // 30
    {FALSE,  SERDES_SPEED_1_25G}, // 31
};

sys_tmg_serdes_temp_soft_table_t tmg_temp_soft_table_10g[] =
{
    {TRUE,  SERDES_SPEED_10_3125G}, // 0
    {TRUE,  SERDES_SPEED_10_3125G}, // 1
    {TRUE,  SERDES_SPEED_10_3125G}, // 2
    {TRUE,  SERDES_SPEED_10_3125G}, // 3
    {TRUE,  SERDES_SPEED_10_3125G}, // 4
    {TRUE,  SERDES_SPEED_10_3125G}, // 5
    {TRUE,  SERDES_SPEED_10_3125G}, // 6
    {TRUE,  SERDES_SPEED_10_3125G}, // 7
    {FALSE,  SERDES_SPEED_10_3125G}, // 8
    {FALSE,  SERDES_SPEED_10_3125G}, // 9
    {FALSE,  SERDES_SPEED_10_3125G}, // 10
    {FALSE,  SERDES_SPEED_10_3125G}, // 11
    {FALSE,  SERDES_SPEED_10_3125G}, // 12
    {FALSE,  SERDES_SPEED_10_3125G}, // 13
    {FALSE,  SERDES_SPEED_10_3125G}, // 14
    {FALSE,  SERDES_SPEED_10_3125G}, // 15
    {FALSE,  SERDES_SPEED_10_3125G}, // 16
    {FALSE,  SERDES_SPEED_10_3125G}, // 17
    {FALSE,  SERDES_SPEED_10_3125G}, // 18
    {FALSE,  SERDES_SPEED_10_3125G}, // 19
    {FALSE,  SERDES_SPEED_10_3125G}, // 20
    {FALSE,  SERDES_SPEED_10_3125G}, // 21
    {FALSE,  SERDES_SPEED_10_3125G}, // 22
    {FALSE,  SERDES_SPEED_10_3125G}, // 23
    {FALSE,  SERDES_SPEED_10_3125G}, // 24
    {FALSE,  SERDES_SPEED_10_3125G}, // 25
    {FALSE,  SERDES_SPEED_10_3125G}, // 26
    {FALSE,  SERDES_SPEED_10_3125G}, // 27
    {FALSE,  SERDES_SPEED_10_3125G}, // 28
    {FALSE,  SERDES_SPEED_10_3125G}, // 29
    {FALSE,  SERDES_SPEED_10_3125G}, // 30
    {FALSE,  SERDES_SPEED_10_3125G}, // 31
};

sys_tmg_serdes_temp_soft_table_t tmg_temp_soft_table_25g[] =
{
    {TRUE,  SERDES_SPEED_25_78125G}, // 0
    {TRUE,  SERDES_SPEED_25_78125G}, // 1
    {TRUE,  SERDES_SPEED_25_78125G}, // 2
    {TRUE,  SERDES_SPEED_25_78125G}, // 3
    {TRUE,  SERDES_SPEED_25_78125G}, // 4
    {TRUE,  SERDES_SPEED_25_78125G}, // 5
    {TRUE,  SERDES_SPEED_25_78125G}, // 6
    {TRUE,  SERDES_SPEED_25_78125G}, // 7
    {FALSE,  SERDES_SPEED_25_78125G}, // 8
    {FALSE,  SERDES_SPEED_25_78125G}, // 9
    {FALSE,  SERDES_SPEED_25_78125G}, // 10
    {FALSE,  SERDES_SPEED_25_78125G}, // 11
    {FALSE,  SERDES_SPEED_25_78125G}, // 12
    {FALSE,  SERDES_SPEED_25_78125G}, // 13
    {FALSE,  SERDES_SPEED_25_78125G}, // 14
    {FALSE,  SERDES_SPEED_25_78125G}, // 15
    {FALSE,  SERDES_SPEED_25_78125G}, // 16
    {FALSE,  SERDES_SPEED_25_78125G}, // 17
    {FALSE,  SERDES_SPEED_25_78125G}, // 18
    {FALSE,  SERDES_SPEED_25_78125G}, // 19
    {FALSE,  SERDES_SPEED_25_78125G}, // 20
    {FALSE,  SERDES_SPEED_25_78125G}, // 21
    {FALSE,  SERDES_SPEED_25_78125G}, // 22
    {FALSE,  SERDES_SPEED_25_78125G}, // 23
    {FALSE,  SERDES_SPEED_25_78125G}, // 24
    {FALSE,  SERDES_SPEED_25_78125G}, // 25
    {FALSE,  SERDES_SPEED_25_78125G}, // 26
    {FALSE,  SERDES_SPEED_25_78125G}, // 27
    {FALSE,  SERDES_SPEED_25_78125G}, // 28
    {FALSE,  SERDES_SPEED_25_78125G}, // 29
    {FALSE,  SERDES_SPEED_25_78125G}, // 30
    {FALSE,  SERDES_SPEED_25_78125G}, // 31
};


uint32 g_pll_cfg_by_serdes_speed[Hss32GPll_TOTALCNT][TMG_SERDES_SPEED_TOTALCNT] = {
    /* 1_25G    3_125G      5G      5_15625G    10G     10_3125G    25_78125G       10_9G       11_4G       12_5G       12_9G       27_7G       27_3G       28_125G*/
      {6,       6,          6,        6,          6,          6,        6,          6,          6,          6,          6,          6,          6,          6},     /*Hss32GPll_cfgRefRange,        */
      {1,       1,          1,        1,          1,          1,        1,          1,          1,          1,          1,          1,          1,          1},     /*Hss32GPll_cfgRefRawClkDiv2En, */
      {0,       0,          0,        0,          0,          0,        0,          0,          0,          0,          0,          0,          0,          0},     /*Hss32GPll_cfgPllClkDiv4En,    */
      {120,     120,        120,      120,        120,        120,      120,        120,        108,        120,        132,        127,        120,        120},   /*Hss32GPll_cfgPllMulti,        */
      {1,       1,          1,        1,          1,          1,        1,          1,          3,          1,          4,          5,          4,          1},     /*Hss32GPll_cfgPllTxClkDiv,     */
      {1,       1,          1,        2,          1,          2,        2,          1,          1,          1,          1,          1,          1,          2},     /*Hss32GPll_cfgPllWordClkDiv,   */
      {0,       0,          0,        0,          0,          0,        0,          0,          0,          0,          0,          0,          0,          0},     /*Hss32GPll_cfgPllSscEn,        */
      {0,       0,          0,        0,          0,          0,        0,          0,          0,          0,          0,          0,          0,          0},     /*Hss32GPll_cfgPllSscUpSpread,  */
      {0,       0,          0,        0,          0,          0,        0,          0,          0,          0,          0,          0,          0,          0},     /*Hss32GPll_cfgPllSscPeak,      */
      {0,       0,          0,        0,          0,          0,        0,          0,          0,          0,          0,          0,          0,          0},     /*Hss32GPll_cfgPllSscStepSize,  */
      {0,       0,          0,        0,          0,          0,        0,          0,          1,          0,          1,          0,          0,          0},     /*Hss32GPll_cfgPllFracEn,       */
      {0,       0,          0,        0,          0,          0,        0,          0,          49152,      0,          26214,      0,          0,          0},     /*Hss32GPll_cfgPllFracQuot,     */
      {0,       0,          0,        0,          0,          0,        0,          0,          0,          0,          2,          0,          0,          0},     /*Hss32GPll_cfgPllFracDen,      */
      {0,       0,          0,        0,          0,          0,        0,          0,          1,          0,          5,          0,          0,          0},     /*Hss32GPll_cfgPllFracRem,      */
      {0,       0,          0,        0,          0,          0,        0,          0,          0,          0,          0,          0,          0,          0},     /*Hss32GPll_cfgRefLaneClkEn,    */
      {0,       0,          0,        0,          0,          0,        0,          0,          0,          0,          0,          0,          0,          0},     /*Hss32GPll_cfgPllCalDis,       */
      {75,      75,         75,       75,         75,         75,       75,         75,         75,         75,         75,         75,         75,         75},    /*Hss32GPll_cfgPllBwThrd,       */
      {1583,    1583,       1583,     1583,       1583,       1583,     1583,       1583,       1583,       1583,       1583,       1583,       1583,       1583},  /*Hss32GPll_cfgPllBwLow,        */
      {1583,    1583,       1583,     1583,       1583,       1583,     1583,       1583,       1583,       1583,       1583,       1583,       1583,       1583},  /*Hss32GPll_cfgPllBwHigh,       */
      {0,       0,          0,        0,          0,          0,        0,          0,          0,          0,          0,          0,          0,          0},     /*Hss32GPll_cfgPllCtlBufBypass, */
      {0,       0,          0,        0,          0,          0,        0,          0,          0,          0,          0,          0,          0,          0},     /*Hss32GPll_cfgPllShortLockEn,  */
      {0,       0,          0,        0,          0,          0,        0,          0,          0,          0,          0,          0,          0,          0},     /*Hss32GPll_cfgRefClkSel     ,  */
};

uint32 g_comm_cfg[Hss32GCom_TOTALCNT] =
{
    /* cfgRefClkPllaDiv    cfgRefClkPllbDiv    cfgHssSramBootloadBypass cfgRxTermOffset    cfgTxdnTermOffset    cfgTxupTermOffset    cfgSupMisc    cfgRxVrefCtrl */
    1,                     1,                  0,                      0,                  0,                  0,                   0,             5
};

uint32 g_tx_cfg_by_serdes_speed[Hss32GTxPerLane_TOTALCNT][TMG_SERDES_SPEED_TOTALCNT] = {

    /* 1_25G      3_125G      5G         5_15625G      10G      10_3125G    25_78125G   10_9G       11_4G       12_5G       12_9G       27_7G       27_3G       28_125G*/
    {128,         128,        0,            0,          0,        0,        0,          0,          0,          0,          0,          0,          0,          0},   /*Hss32GTxPerLane_cfgTxMisc,               */
    {8,           8,          8,            8,          8,        8,        8,          8,          8,          8,          8,          8,          8,          8},   /*Hss32GTxPerLane_cfgTxDccCtrlDiffRange,   */
    {8,           8,          8,            8,          8,        8,        8,          8,          8,          8,          8,          8,          8,          8},   /*Hss32GTxPerLane_cfgTxDccCtrlCmRange,     */
    {1,           1,          5,            4,          5,        4,        4,          4,          4,          4,          4,          4,          4,          4},   /*Hss32GTxPerLane_cfgTxWidth,              */
    {18,          26,         18,           83,         16,       83,       26,         79,         79,         105,        71,         105,        105,        105}, /*Hss32GTxPerLane_cfgTxRopllCpCtlIntg,     */
    {99,          101,        99,           83,         81,       83,       73,         79,         79,         67,         71,         102,        102,        61},  /*Hss32GTxPerLane_cfgTxRopllCpCtlProp,     */
    {4,           4,          4,            4,          5,        4,        4,          4,          4,          4,          4,          4,          4,          4},   /*Hss32GTxPerLane_cfgTxRopllRcFilter,      */
    {3,           3,          3,            3,          3,        3,        3,          3,          3,          3,          3,          3,          3,          3},   /*Hss32GTxPerLane_cfgTxRopllV2iMode,       */
    {3,           2,          3,            2,          3,        2,        2,          2,          2,          2,          2,          3,          3,          0},   /*Hss32GTxPerLane_cfgTxRopllVcoLowFreq,    */
    {1,           2,          2,            1,          1,        1,        0,          1,          1,          1,          1,          0,          0,          0},   /*Hss32GTxPerLane_cfgTxRopllPostDiv,       */
    {4,           3,          2,            2,          1,        1,        0,          1,          1,          1,          1,          0,          0,          0},   /*Hss32GTxPerLane_cfgTxRate,               */
    {0,           0,          0,            0,          0,        0,        0,          0,          0,          0,          0,          0,          0,          0},   /*Hss32GTxPerLane_cfgTxTermCtrl,           */
    {0,           0,          0,            0,          0,        0,        0,          0,          0,          0,          0,          0,          0,          0},   /*Hss32GTxPerLane_cfgTxDlyCalEn,           */
    {0xffffffff,  0xffffffff, 0xffffffff,   4,          6,        6,        6,          6,          6,          6,          6,          6,          6,          8},   /*Hss32GTxPerLane_cfgTxPllWordClkFreq,     */
    {0,           0,          0,            0,          0,        0,        0,          0,          0,          0,          0,          0,          0,          0},   /*Hss32GTxPerLane_cfgTxDualCntxEn,         */
    {0,           0,          0,            0,          0,        0,        0,          0,          0,          0,          0,          0,          0,          0},   /*Hss32GTxPerLane_cfgTxRopllBypass,        */
    {15,          6,          15,           5,          15,       5,        4,          6,          1,          6,          1,          1,          3,          4},   /*Hss32GTxPerLane_cfgTxRopllRefDiv,        */
    {0,           0,          0,            0,          0,        0,        0,          0,          0,          0,          0,          0,          0,          0},   /*Hss32GTxPerLane_cfgTxRopllRefSel,        */
    {32,          16,         32,           11,         32,      11,       11,          14,         8,          16,         10,         14,         35,         12},  /*Hss32GTxPerLane_cfgTxRopllFbDiv,         */
    {5,           4,          4,            4,          4,        4,        4,          4,          4,          4,          4,          4,          4,          4},   /*Hss32GTxPerLane_cfgTxRopllOutDiv,        */
    {3,           3,          3,            2,          3,        2,        2,          2,          2,          2,          2,          2,          2,          2},   /*Hss32GTxPerLane_cfgTxRopllWordClkDivSel, */
    {0,           0,          0,            0,          1,        0,        0,          0,          0,          0,          0,          0,          0,          0},   /*Hss32GTxPerLane_cfgTxFastEdgeEn,         */
    {0,           0,          0,            0,          0,        0,        1,          0,          0,          0,          0,          1,          1,          1},   /*Hss32GTxPerLane_cfgTxAlignWideXferEn,    */
    {1,           1,          1,            1,          1,        1,        1,          1,          1,          1,          1,          1,          1,          1},   /*Hss32GTxPerLane_cfgTxPllEn*/

};

uint32 g_rx_cfg_by_serdes_speed[Hss32GRxPerLane_TOTALCNT][TMG_SERDES_SPEED_TOTALCNT] = {

    /* 1_25G    3_125G      5G          5_15625G    10G         10_3125G    25_78125G   10_9G       11_4G       12_5G       12_9G       27_7G       27_3G       28_125G*/
    {21,        17,         21,         21,         21,         21,         17,         20,         19,         17,         17,         15,         16,         15},    /* Hss32GRxPerLane_cfgRxRefLoadValue,        */
    {1344,      1360,       1344,       1386,       1344,       1386,       1403,       1400,       1387,       1360,       1411,       1334,       1400,       1350},  /* Hss32GRxPerLane_cfgRxVcoLoadValue,        */
    {18,        18,         18,         18,         18,         18,         19,         18,         18,         18,         18,         18,         18,         18},    /* Hss32GRxPerLane_cfgRxCdrPpmMax,           */
    {0,         0,          0,          0,          0,          0,          0,          12,         0,          0,          0,          0,          0,          0},     /* Hss32GRxPerLane_cfgRxEqAttLevel,          */
    {12,        24,         12,         24,         12,         16,         20,         16,         16,         16,         16,         16,         16,         24},    /* Hss32GRxPerLane_cfgRxEqCtleBoost,         */
    {0,         0,          0,          1,          0,          1,          3,          0,          0,          0,          0,          0,          0,          3},     /* Hss32GRxPerLane_cfgRxEqCtlePole,          */
    {7,         7,          6,          6,          6,          6,          1,          7,          1,          4,          4,          4,          4,          1},     /* Hss32GRxPerLane_cfgRxEqAfeRate,           */
    {4,         28,         4,          16,         4,          16,         16,         4,          8,          8,          8,          8,          8,          20},    /* Hss32GRxPerLane_cfgRxEqVgaGain,           */
    {396,       1300,       1300,       1300,       1300,       396,        2364,       1300,       396,        396,        396,        396,        396,        2364},  /* Hss32GRxPerLane_cfgRxEqAfeConfig,         */
    {0,         0,          0,          5,          0,          12,         12,         0,          15,         15,         15,         15,         15,         10  },    /* Hss32GRxPerLane_cfgRxEqDfeTap1,           */
    {128,       128,        128,        128,        128,        128,        128,        128,        128,        128,        128,        128,        128,        128},   /* Hss32GRxPerLane_cfgRxEqDfeTap2,           */
    {0,         0,          0,          8,          0,          6,          4,          0,          6,          6,          6,          6,          6,          3},     /* Hss32GRxPerLane_cfgRxDeltaIq,             */
    {1059,      1027,       1059,       1059,       1315,       1059,       34,         1315,       1315,       1315,       1315,       1315,       1315,       256},    /* Hss32GRxPerLane_cfgRxCdrVcoConfig,        */
    {11,        11,         11,         11,         1,          11,         11,         11,         11,         11,         11,         11,         11,         11},    /* Hss32GRxPerLane_cfgRxDccCtrlDiffRange,    */
    {11,        11,         11,         11,         11,         11,         11,         11,         11,         11,         11,         11,         11,         11},    /* Hss32GRxPerLane_cfgRxDccCtrlCmRange,      */
    {6,         6,          6,          6,          6,          6,          4,          6,          6,          6,          6,          6,          6,          5},     /* Hss32GRxPerLane_cfgRxSigdetLfThrd,        */
    {2,         2,          2,          2,          2,          2,          2,          2,          2,          3,          3,          4,          4,          2},     /* Hss32GRxPerLane_cfgRxSigdetHfThrd,        */
    {128,       128,        0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0},     /* Hss32GRxPerLane_cfgRxMisc,                */
    {2,         2,          2,          2,          2,          2,          2,          2,          2,          2,          2,          2,          2,          2},     /* Hss32GRxPerLane_cfgRxTermCtrl,            */
    {1,         1,          5,          4,          5,          4,          4,          4,          4,          4,          4,          4,          4,          4},     /* Hss32GRxPerLane_cfgRxWidth,               */
    {4,         3,          2,          2,          1,          1,          0,          1,          1,          1,          1,          0,          0,          0},     /* Hss32GRxPerLane_cfgRxRate,                */
    {1,         1,          0,          1,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0},     /* Hss32GRxPerLane_cfgRxDfeBypass,           */
    {1,         1,          1,          1,          1,          1,          1,          1,          1,          1,          1,          1,          1,          1},     /* Hss32GRxPerLane_cfgRxOffcanCont,          */
    {0,         0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0},     /* Hss32GRxPerLane_cfgRxAdaptCont,           */
    {0,         0,          0,          0,          0,          0,          1,          0,          0,          0,          0,          0,          0,          1},     /* Hss32GRxPerLane_cfgRxEqDfeFloatEn,        */
    {0,         0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0},     /* Hss32GRxPerLane_cfgRxCdrSscEn,            */
    {0,         0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0},     /* Hss32GRxPerLane_cfgRxSigdetHfEn,          */
    {0,         0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0},     /* Hss32GRxPerLane_cfgRxSigdetLfpsFilterEn,  */
    {1,         1,          1,          1,          1,          1,          1,          1,          1,          1,          1,          1,          1,          1},     /* Hss32GRxPerLane_cfgRxTermAcdc,            */
    {0,         0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0,          0},     /* Hss32GRxPerLane_cfgRxAdaptSel,            */
    {0,         0,          0,          0,          0,          4,          4,          4,          4,          4,          4,          4,          4,          4},     /* Hss32GRxPerLane_cfgRxAdaptMode,           */
    {0,         0,          0,          0,          0,          1,          1,          1,          1,          1,          1,          1,          1,          1},     /* Hss32GRxPerLane_cfgRxAdaptEn, */
    {1,         1,          1,          1,          1,          1,          1,          1,          1,          1,          1,          1,          1,          1},     /* Hss32GRxPerLane_cfgRxTermEn,  */
};

#ifdef TMG_SERDES_SIM
static uint16 mem[2][0x4880];

void _sys_tmg_serdes_load_internal_register(uint16 macro_id)
{
    uint16 serdes_id = 0;
    uint16 address   = 0;
    uint8 inner_lane = 0;
    _sys_tmg_serdes_field_t* p_field_info = NULL;
    /*load sup level*/
    p_field_info = REG_STR(TMG_SERDES_ANLT_TOP_AN_INT_ENABLE);
    TMG_SERDES_GET_ADDRESS(p_field_info->type, 0, p_field_info->offset, address);
    mem[macro_id][address] = 0;

    /*load lane level*/
    for(inner_lane = 0; inner_lane < 4; inner_lane++)
    {
        serdes_id = SYS_TMG_LANE_NUM_PER_HSS * macro_id + inner_lane;

        p_field_info = REG_STR(TMG_SERDES_AN_ADV3);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_AN_ADV2);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_AN_ADV1);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_AN_AUTO_NP_EN);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0x8001;

        p_field_info = REG_STR(TMG_SERDES_XNP_TX3);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_XNP_TX2);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_XNP_TX1);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0x3001;

        p_field_info = REG_STR(TMG_SERDES_VR_UF_XNP_TX3);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_VR_UF_XNP_TX2);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_VR_UF_XNP_TX1);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_AN_INT_ENABLE_AN_GOOD_CHECK);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_VR_AN_MODE_CTRL_RX_POL_INV);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0x8001;

        p_field_info = REG_STR(TMG_SERDES_AN_ENABLE);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0x3000;

        p_field_info = REG_STR(TMG_SERDES_LT_ENABLE);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_VR_AN_LINK_FAIL_INHIBIT_TIMER_EN);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0x7;

        p_field_info = REG_STR(TMG_SERDES_LT_CL72_SEL);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 1;

        p_field_info = REG_STR(TMG_SERDES_LT_START_EN_AFTR_AN);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_LT_MAX_WAIT_TIMEL);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0xb1c8;

        p_field_info = REG_STR(TMG_SERDES_LT_MAX_WAIT_TIMEH);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0x99a;

        p_field_info = REG_STR(TMG_SERDES_LT_LINKRDY_WAIT_TIME);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0x6b08;

        p_field_info = REG_STR(TMG_SERDES_LT_RX_TRAIN_TIME_L);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0x3778;

        p_field_info = REG_STR(TMG_SERDES_LT_RX_TRAIN_TIME_H);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0x5c3;

        p_field_info = REG_STR(TMG_SERDES_LT_RX_EQ_SEQ_PAR_SEL);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0x70;


        p_field_info = REG_STR(TMG_SERDES_TX_PRBS_MODE);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_RX_PRBS_MODE);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_PRBS_SYNC);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_PRBS_TRIGGER_ERR);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 0;

        p_field_info = REG_STR(TMG_SERDES_RX_CDR_DETECTOR_EN);
        TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, address);
        mem[macro_id][address] = 5;

    }
}

#endif
int32
sys_tmg_serdes_set_hss_tx_rst(uint8 lchip, uint16 psd, uint32 rst)
{
    uint8  hss      = SYS_TMG_GET_HSS_ID_BY_SERDES(psd);
    uint8  lane     = SYS_TMG_GET_INNER_LANE_BY_SERDES(psd);
    uint32 tbl_id   = Hss32GReset_t;
    uint32 fld_id   = 0;
    uint32 index    = DRV_INS(hss, 0);
    uint32 cmd      = 0;
    Hss32GReset_m   hss_rst;

    dmps_Hss32GReset_resetHssL0TxGb_f(lane, fld_id);
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hss_rst));
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &rst, &hss_rst, hss, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hss_rst));

    return CTC_E_NONE;
}

/*Hss32GMacroCfg_cfgHssL0TxDataOutSel*/
/*Hss32GMacroCfg_cfgHssL0RxDataOutSel*/
int32
sys_tmg_serdes_set_trx_dataout_sel(uint8 lchip, uint8 hss_id, uint8 psd_num, uint16 psd[], uint8 if_mode)
{
    uint8  idx              = 0;
    uint32 cmd              = 0;
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 index            = 0;
    uint32 val_tdo          = 0;
    uint32 val_rdo          = 0;
    Hss32GMacroCfg_m        hss_cfg;

    switch(if_mode)
    {
        case CTC_CHIP_SERDES_SGMII_MODE:
        case CTC_CHIP_SERDES_2DOT5G_MODE:
            val_tdo = 0;
            val_rdo = 0;
            break;
        case CTC_CHIP_SERDES_XXVG_MODE:
        case CTC_CHIP_SERDES_LG_MODE:
        case CTC_CHIP_SERDES_CG_MODE:
            val_tdo = 4;
            val_rdo = 2;
            break;
        case CTC_CHIP_SERDES_XFI_MODE:
        case CTC_CHIP_SERDES_XLG_MODE:
        default:
            val_tdo = 2;
            val_rdo = 2;
            break;
    }

    index = DRV_INS(hss_id, 0);
    tbl_id = Hss32GMacroCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hss_cfg));
    for(idx = 0; idx < psd_num; idx++)
    {
        dmps_Hss32GMacroCfg_cfgHssL0TxDataOutSel_f(SYS_TMG_GET_INNER_LANE_BY_SERDES(psd[idx]), fld_id);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val_tdo, &hss_cfg, hss_id, 0);
        dmps_Hss32GMacroCfg_cfgHssL0RxDataOutSel_f(SYS_TMG_GET_INNER_LANE_BY_SERDES(psd[idx]), fld_id);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val_rdo, &hss_cfg, hss_id, 0);
    }
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hss_cfg));

    return CTC_E_NONE;
}

/*Hss32GMacroCfg_cfgHssL0TxBitReverse*/
/*Hss32GMacroCfg_cfgHssL0RxBitReverse*/
int32
sys_tmg_serdes_set_trx_bit_reverse(uint8 lchip, uint8 hss_id, uint8 psd_num, uint16 psd[], uint32 value)
{
    uint8  idx              = 0;
    uint32 cmd              = 0;
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 index            = 0;
    Hss32GMacroCfg_m        hss_cfg;

    index = DRV_INS(hss_id, 0);
    tbl_id = Hss32GMacroCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hss_cfg));
    for(idx = 0; idx < psd_num; idx++)
    {
        dmps_Hss32GMacroCfg_cfgHssL0TxBitReverse_f(SYS_TMG_GET_INNER_LANE_BY_SERDES(psd[idx]), fld_id);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &hss_cfg, hss_id, 0);
        dmps_Hss32GMacroCfg_cfgHssL0RxBitReverse_f(SYS_TMG_GET_INNER_LANE_BY_SERDES(psd[idx]), fld_id);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &hss_cfg, hss_id, 0);
    }
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hss_cfg));

    return CTC_E_NONE;
}

int32
sys_tmg_serdes_set_hss_clktree_cfg(uint8 lchip, uint8 hss_id, uint8 psd_num, uint16 psd[], uint8 if_mode)
{
    uint8  lr_flag          = 0;
    uint16 mac_id           = 0;
    uint8  idx              = 0;
    uint32 cmd              = 0;
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 index            = 0;
    uint32 val_h1s          = 0;
    uint32 val_h2s          = 0;
    uint32 val_p1s          = 0;
    uint32 val_p2s          = 0;
    uint32 val_pms          = 0;
    uint32 val_pml          = 0;
    Hss32GClkTreeCfg_m      clk_tre;

    CTC_ERROR_RETURN(sys_usw_dmps_db_get_relative_id(lchip, DMPS_DB_TYPE_PSD, psd[0], DMPS_DB_TYPE_MAC, NULL, &mac_id));
    lr_flag = (2 > SYS_TMG_GET_QUAD_MAC_ID(mac_id)) ? 0 : 1;

    switch(if_mode)
    {
        case CTC_CHIP_SERDES_SGMII_MODE:
            val_h1s = 0;
            val_h2s = 1;
            val_p1s = 0;
            val_p2s = 1;
            val_pms = 0;
            val_pml = 0;
            break;
        case CTC_CHIP_SERDES_2DOT5G_MODE:
            val_h1s = 0;
            val_h2s = 0;
            val_p1s = 0;
            val_p2s = 0;
            val_pms = 0;
            val_pml = 0;
            break;
        case CTC_CHIP_SERDES_XXVG_MODE:
            val_h1s = 1;
            val_h2s = 0;
            val_p1s = 0;
            val_p2s = 1;
            val_pms = 0;
            val_pml = 0;
            break;
        case CTC_CHIP_SERDES_LG_MODE:
            val_h1s = 1;
            val_h2s = 0;
            val_p1s = 0;
            val_p2s = 1;
            val_pms = (lr_flag) ? 1 : 0;
            val_pml = 1;
            break;
        case CTC_CHIP_SERDES_CG_MODE:
            val_h1s = 1;
            val_h2s = 0;
            val_p1s = 0;
            val_p2s = 1;
            val_pms = 1;
            val_pml = 1;
            break;
        case CTC_CHIP_SERDES_XFI_MODE:
            val_h1s = 1;
            val_h2s = 0;
            val_p1s = 1;
            val_p2s = 0;
            val_pms = 0;
            val_pml = 0;
            break;
        case CTC_CHIP_SERDES_XLG_MODE:
        default:
            val_h1s = 1;
            val_h2s = 0;
            val_p1s = 1;
            val_p2s = 0;
            val_pms = 1;
            val_pml = 1;
            break;
    }

    index = DRV_INS(hss_id, 0);
    tbl_id = Hss32GClkTreeCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &clk_tre));
    for(idx = 0; idx < psd_num; idx++)
    {
        dmps_Hss32GClkTreeCfg_cfgClockHssL0TxL1Sel_f(SYS_TMG_GET_INNER_LANE_BY_SERDES(psd[idx]), fld_id);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val_h1s, &clk_tre, hss_id, 0);
        dmps_Hss32GClkTreeCfg_cfgClockHssL0TxL2Sel_f(SYS_TMG_GET_INNER_LANE_BY_SERDES(psd[idx]), fld_id);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val_h2s, &clk_tre, hss_id, 0);
        dmps_Hss32GClkTreeCfg_cfgClockPcsL0TxL1Sel_f(SYS_TMG_GET_INNER_LANE_BY_SERDES(psd[idx]), fld_id);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val_p1s, &clk_tre, hss_id, 0);
        dmps_Hss32GClkTreeCfg_cfgClockPcsL0TxL2Sel_f(SYS_TMG_GET_INNER_LANE_BY_SERDES(psd[idx]), fld_id);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val_p2s, &clk_tre, hss_id, 0);
        dmps_Hss32GClkTreeCfg_cfgClockPcsL0TxMstSel_f(SYS_TMG_GET_INNER_LANE_BY_SERDES(psd[idx]), fld_id);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val_pms, &clk_tre, hss_id, 0);
        dmps_Hss32GClkTreeCfg_cfgClockPcsL0TxMultLane_f(SYS_TMG_GET_INNER_LANE_BY_SERDES(psd[idx]), fld_id);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val_pml, &clk_tre, hss_id, 0);
    }
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &clk_tre));

    return CTC_E_NONE;
}

uint8 _sys_tmg_serdes_get_dmps_speed(uint8 txrx_speed)
{
    uint8 serdes_speed = 0;

    switch(serdes_speed)
    {
        case TMG_SERDES_SPEED_1_25G:
            txrx_speed = SERDES_SPEED_1_25G;
            break;
        case TMG_SERDES_SPEED_3_125G:
            txrx_speed = SERDES_SPEED_3_125G;
            break;
        case TMG_SERDES_SPEED_10_3125G:
            txrx_speed = SERDES_SPEED_10_3125G;
            break;
        case TMG_SERDES_SPEED_25_78125G:
            txrx_speed = SERDES_SPEED_25_78125G;
            break;
        case TMG_SERDES_SPEED_10_9375G:
            txrx_speed = SERDES_SPEED_10_9375G;
            break;
        case TMG_SERDES_SPEED_11_40625G:
            txrx_speed = SERDES_SPEED_11_40625G;
            break;
        case TMG_SERDES_SPEED_12_5G:
            txrx_speed = SERDES_SPEED_12_5G;
            break;
        case TMG_SERDES_SPEED_12_96875G:
            txrx_speed = SERDES_SPEED_12_96875G;
            break;
        case TMG_SERDES_SPEED_27_34375G:
            txrx_speed = SERDES_SPEED_27_34375G;
            break;
        case TMG_SERDES_SPEED_27_78125G:
            txrx_speed = SERDES_SPEED_27_78125G;
            break;
        case TMG_SERDES_SPEED_28_125G:
            txrx_speed = SERDES_SPEED_28_125G;
            break;
        default:
            txrx_speed = SERDES_SPEED_MAX;
            break;    
    }

    return CTC_E_NONE;
}

uint8 _sys_tmg_serdes_get_related_speed(uint8 serdes_speed)
{
    uint8 txrx_speed = 0;
    switch(serdes_speed)
    {
        case SERDES_SPEED_1_25G:
            txrx_speed = TMG_SERDES_SPEED_1_25G;
            break;
        case SERDES_SPEED_3_125G:
            txrx_speed = TMG_SERDES_SPEED_3_125G;
            break;
        case SERDES_SPEED_10_3125G:
            txrx_speed = TMG_SERDES_SPEED_10_3125G;
            break;
        case SERDES_SPEED_25_78125G:
            txrx_speed = TMG_SERDES_SPEED_25_78125G;
            break;
        case SERDES_SPEED_10_9375G:
            txrx_speed = TMG_SERDES_SPEED_10_9375G;
            break;
        case SERDES_SPEED_11_40625G:
            txrx_speed = TMG_SERDES_SPEED_11_40625G;
            break;
        case SERDES_SPEED_12_5G:
            txrx_speed = TMG_SERDES_SPEED_12_5G;
            break;
        case SERDES_SPEED_12_96875G:
            txrx_speed = TMG_SERDES_SPEED_12_96875G;
            break;
        case SERDES_SPEED_27_34375G:
            txrx_speed = TMG_SERDES_SPEED_27_34375G;
            break;
        case SERDES_SPEED_27_78125G:
            txrx_speed = TMG_SERDES_SPEED_27_78125G;
            break;
        case SERDES_SPEED_28_125G:
            txrx_speed = TMG_SERDES_SPEED_28_125G;
            break;
    }

    return txrx_speed;
}

int32 _sys_tmg_serdes_cfg_pll(uint8 lchip, uint16 macro_id, uint8 pll_id, uint8 serdes_speed)
{
    uint8 field_idx = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint8  txrx_speed = 0;

    Hss32GPllCfg_m pll_cfg;

    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    txrx_speed = _sys_tmg_serdes_get_related_speed(serdes_speed);

    /*step 1 read table*/
    cmd     = DRV_IOR(Hss32GPllCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id,0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pll_cfg));

    /*step 2 change field */
    for(field_idx = 0; field_idx < Hss32GPll_TOTALCNT; field_idx++)
    {
        switch(field_idx)
        {
            case Hss32GPll_cfgRefRange:
                dmps_Hss32GPllCfg_hssPllCfg_0_cfgRefRange_f(pll_id, fld_id);
                break;
            case Hss32GPll_cfgRefRawClkDiv2En:
                dmps_Hss32GPllCfg_hssPllCfg_0_cfgRefRawClkDiv2En_f(pll_id, fld_id);
                break;
            case Hss32GPll_cfgPllClkDiv4En:
                dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllClkDiv4En_f(pll_id, fld_id);
                break;
            case Hss32GPll_cfgPllMulti:
                dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllMulti_f(pll_id, fld_id);
                break;
            case Hss32GPll_cfgPllTxClkDiv:
                dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllTxClkDiv_f(pll_id, fld_id);
                break;
            case Hss32GPll_cfgPllWordClkDiv:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllWordClkDiv_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllSscEn:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllSscEn_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllSscUpSpread:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllSscUpSpread_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllSscPeak:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllSscPeak_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllSscStepSize:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllSscStepSize_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllFracEn:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllFracEn_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllFracQuot:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllFracQuot_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllFracDen:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllFracDen_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllFracRem:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllFracRem_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgRefLaneClkEn:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgRefLaneClkEn_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllCalDis:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllCalDis_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllBwThrd:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllBwThrd_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllBwLow:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllBwLow_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllBwHigh:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllBwHigh_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllCtlBufBypass:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllCtlBufBypass_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgPllShortLockEn:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgPllShortLockEn_f(pll_id, fld_id);
               break;
            case Hss32GPll_cfgRefClkSel:
               dmps_Hss32GPllCfg_hssPllCfg_0_cfgRefClkSel_f(pll_id, fld_id);
               break;
        }

        value  = g_pll_cfg_by_serdes_speed[field_idx][txrx_speed];
        DRV_IOW_FIELD_NZ(lchip, Hss32GPllCfg_t, fld_id, &value, &pll_cfg, macro_id, 0);

    }

    cmd     = DRV_IOW(Hss32GPllCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id,0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pll_cfg));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_cfg_com(uint8 lchip, uint16 macro_id)
{
    uint8 field_idx = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;

    Hss32GComCfg_m com_cfg;

    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    if(g_sram_bootloader_bypass == 1)
    {
        g_comm_cfg[Hss32GCom_cfgHssSramBootloadBypass] = 1;
    }

    /*step 1 read table*/
    cmd     = DRV_IOR(Hss32GComCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id,0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &com_cfg));

    for(field_idx = 0; field_idx < Hss32GCom_TOTALCNT; field_idx++)
    {
        switch(field_idx)
        {
             case Hss32GCom_cfgRefClkPllaDiv:
                fld_id = Hss32GComCfg_cfgRefClkPllaDiv_f;
                break;
             case Hss32GCom_cfgRefClkPllbDiv:
                fld_id = Hss32GComCfg_cfgRefClkPllbDiv_f;
                break;
             case Hss32GCom_cfgHssSramBootloadBypass:
                fld_id = Hss32GComCfg_cfgHssSramBootloadBypass_f;
                break;
             case Hss32GCom_cfgRxTermOffset:
                fld_id = Hss32GComCfg_cfgRxTermOffset_f;
                break;
             case Hss32GCom_cfgTxdnTermOffset:
                fld_id = Hss32GComCfg_cfgTxdnTermOffset_f;
                break;
             case Hss32GCom_cfgTxupTermOffset:
                fld_id = Hss32GComCfg_cfgTxupTermOffset_f;
                break;
             case Hss32GCom_cfgSupMisc:
                fld_id = Hss32GComCfg_cfgSupMisc_f;
                break;
             case Hss32GCom_cfgRxVrefCtrl:
                fld_id = Hss32GComCfg_cfgRxVrefCtrl_f;
                break;
        }

        value  = g_comm_cfg[field_idx];
        DRV_IOW_FIELD_NZ(lchip, Hss32GComCfg_t, fld_id, &value, &com_cfg, macro_id, 0);
    }

    cmd     = DRV_IOW(Hss32GComCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id,0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &com_cfg));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_cfg_tx(uint8 lchip, uint16 serdes_id, uint8 serdes_speed, uint8 is_init)
{
    uint8 field_idx = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint8  macro_id = 0;
    uint8  lane_id  = 0;
    uint8  txrx_speed = 0;

    Hss32GTxPerLaneCfg_m tx_cfg;

    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    macro_id = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id  = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    txrx_speed = _sys_tmg_serdes_get_related_speed(serdes_speed);

    /*step 1 read table*/
    cmd     = DRV_IOR(Hss32GTxPerLaneCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id,0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_cfg));

    for(field_idx = 0; field_idx < Hss32GTxPerLane_TOTALCNT; field_idx++)
    {
        switch(field_idx)
        {
            case Hss32GTxPerLane_cfgTxMisc:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxMisc_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxDccCtrlDiffRange:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxDccCtrlDiffRange_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxDccCtrlCmRange:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxDccCtrlCmRange_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxWidth:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxWidth_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRopllCpCtlIntg:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllCpCtlIntg_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRopllCpCtlProp:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllCpCtlProp_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRopllRcFilter:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllRcFilter_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRopllV2iMode:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllV2iMode_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRopllVcoLowFreq:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllVcoLowFreq_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRopllPostDiv:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllPostDiv_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRate:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRate_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxTermCtrl:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxTermCtrl_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxDlyCalEn:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxDlyCalEn_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxPllWordClkFreq:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxPllWordClkFreq_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxDualCntxEn:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxDualCntxEn_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRopllBypass:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllBypass_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRopllRefDiv:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllRefDiv_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRopllRefSel:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllRefSel_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRopllFbDiv:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllFbDiv_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRopllOutDiv:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllOutDiv_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxRopllWordClkDivSel:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllWordClkDivSel_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxFastEdgeEn:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxFastEdgeEn_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxAlignWideXferEn:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxAlignWideXferEn_f(lane_id, fld_id);
                break;
             case Hss32GTxPerLane_cfgTxPllEn:
                dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxPllEn_f(lane_id, fld_id);
                break;
        }

        value  = g_tx_cfg_by_serdes_speed[field_idx][txrx_speed];

        if(Hss32GTxPerLane_cfgTxPllWordClkFreq == field_idx && value == SYS_DMPS_INVALID_U32)
        {
            continue;
        }

        DRV_IOW_FIELD_NZ(lchip, Hss32GTxPerLaneCfg_t, fld_id, &value, &tx_cfg, macro_id, 0);

    }

    cmd     = DRV_IOW(Hss32GTxPerLaneCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id,0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_cfg));

    if(!is_init)
    {
#ifdef TMG_SERDES_SIM
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
#endif
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip, serdes_id, DMPS_TX, TRUE));
        CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_TX, 1));
#ifdef TMG_SERDES_SIM
            SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
#endif
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip, serdes_id, DMPS_TX, FALSE));
    }

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_cfg_rx(uint8 lchip, uint16 serdes_id, uint8 serdes_speed, uint8 is_init)
{
    uint8 field_idx = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint8  macro_id   = 0;
    uint8  lane_id    = 0;
    uint8  txrx_speed = 0;

    Hss32GRxPerLaneCfg_m rx_cfg;

    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    txrx_speed = _sys_tmg_serdes_get_related_speed(serdes_speed);

    macro_id = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id  = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    /*step 1 read table*/
    cmd     = DRV_IOR(Hss32GRxPerLaneCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id,0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_cfg));

    for(field_idx = 0; field_idx < Hss32GRxPerLane_TOTALCNT; field_idx++)
    {
        switch(field_idx)
        {
             case Hss32GRxPerLane_cfgRxRefLoadValue:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxRefLoadValue_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxVcoLoadValue:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxVcoLoadValue_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxCdrPpmMax:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxCdrPpmMax_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxEqAttLevel:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqAttLevel_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxEqCtleBoost:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqCtleBoost_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxEqCtlePole:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqCtlePole_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxEqAfeRate:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqAfeRate_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxEqVgaGain:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqVgaGain_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxEqAfeConfig:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqAfeConfig_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxEqDfeTap1:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqDfeTap1_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxEqDfeTap2:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqDfeTap2_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxDeltaIq:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxDeltaIq_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxCdrVcoConfig:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxCdrVcoConfig_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxDccCtrlDiffRange:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxDccCtrlDiffRange_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxDccCtrlCmRange:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxDccCtrlCmRange_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxSigdetLfThrd:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxSigdetLfThrd_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxSigdetHfThrd:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxSigdetHfThrd_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxMisc:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxMisc_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxTermCtrl:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxTermCtrl_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxWidth:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxWidth_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxRate:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxRate_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxDfeBypass:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxDfeBypass_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxOffcanCont:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxOffcanCont_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxAdaptCont:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxAdaptCont_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxEqDfeFloatEn:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqDfeFloatEn_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxCdrSscEn:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxCdrSscEn_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxSigdetHfEn:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxSigdetHfEn_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxSigdetLfpsFilterEn:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxSigdetLfpsFilterEn_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxTermAcdc:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxTermAcdc_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxAdaptSel:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxAdaptSel_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxAdaptMode:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxAdaptMode_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxAdaptEn:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxAdaptEn_f(lane_id, fld_id);
                break;
             case Hss32GRxPerLane_cfgRxTermEn:
                dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxTermEn_f(lane_id, fld_id);
                break;
        }

        value  = g_rx_cfg_by_serdes_speed[field_idx][txrx_speed];
        DRV_IOW_FIELD_NZ(lchip, Hss32GRxPerLaneCfg_t, fld_id, &value, &rx_cfg, macro_id, 0);

    }

    cmd     = DRV_IOW(Hss32GRxPerLaneCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id,0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_cfg));

    if(!is_init)
    {
#ifdef TMG_SERDES_SIM
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
#endif
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip, serdes_id, DMPS_RX, TRUE));
        CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_RX, 1));
#ifdef TMG_SERDES_SIM
            SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
#endif
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip, serdes_id, DMPS_RX, FALSE));
    }
    return CTC_E_NONE;
}

void _sys_tmg_serdes_wait_ms(uint8 ms)
{
    sal_task_sleep(ms);
}

int32 _sys_tmg_serdes_write_reg(uint8 lchip, uint16 hss_id, uint16 reg, uint16 data)
{
#if defined(TMG_SERDES_SIM)
    uint32 mon_addr[SYS_TMG_MAX_HSS_NUM + 1] = {0x602489b0, 0x60248bb0, 0x602c89b0, 0x602c8bb0, 0x603489b0, 0x60348bb0, 0x603c89b0, 0x603c8bb0, 0x604489b0, 0x60448bb0, 0x682489b0, 0x68248bb0, 0x682c89b0, 0x682c8bb0, 0x683489b0, 0x68348bb0, 0x683c89b0, 0x683c8bb0, 0x684489b0, 0x68448bb0, 0x544425b0};
#endif
    uint32 index    = 0;
    uint32 cmd      = 0;
    uint32 value    = 0;
    uint8  macro_id = 0;
    uint8  acc_id   = 0;

    Hss32GRegAccCtl_m       acc_ctl;

#if defined(TMG_SERDES_SIM) || (!defined(EMULATION_ENV) && (0 == SDK_WORK_PLATFORM))
    Hss32GRegAccResult_m    acc_mon;
#endif

#if !defined(EMULATION_ENV) && (0 == SDK_WORK_PLATFORM)
    uint32 acc_timeout = 10000;
#endif

    macro_id = hss_id;
    acc_id   = 0;

    index = DRV_INS(macro_id, 0);
    cmd   = DRV_IOR(Hss32GRegAccCtl_t, DRV_ENTRY_FLAG);

    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_ctl));

    /* operate write*/
    value = acc_id;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccId_f, &value, &acc_ctl, macro_id, 0);
    value = reg;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccAddr_f, &value, &acc_ctl, macro_id, 0);
    value = 0;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccIsRead_f, &value, &acc_ctl, macro_id, 0);
    value = data;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccWdata_f, &value, &acc_ctl, macro_id, 0);
    value = 1;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccValid_f, &value, &acc_ctl, macro_id, 0);

    cmd   = DRV_IOW(Hss32GRegAccCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_ctl));

#if !defined(EMULATION_ENV) && (0 == SDK_WORK_PLATFORM)

    /*polling acc ack*/
    cmd = DRV_IOR(Hss32GRegAccResult_t, DRV_ENTRY_FLAG);

    for(acc_timeout = 10000; acc_timeout > 0; acc_timeout--)
    {
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_mon));
        DRV_IOR_FIELD(lchip, Hss32GRegAccResult_t, Hss32GRegAccResult_hssAccAck_f, &value, &acc_mon);
        if(value != 0)
        {
            break;
        }
    }

    /* clear acc ack*/

    value = 0;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccResult_t, Hss32GRegAccResult_hssAccAck_f, &value, &acc_mon, macro_id, 0);
    cmd = DRV_IOW(Hss32GRegAccResult_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_mon));

    if(0 == acc_timeout)
    {
        return CTC_E_HW_FAIL;
    }

    (void)_sys_tmg_serdes_wait_ms(1);

#elif defined(TMG_SERDES_SIM)

    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", mon_addr[macro_id], 0x80000000, 0x80000000, 1000000000);

    /*clear ack*/
    cmd = DRV_IOR(Hss32GRegAccResult_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_mon));

    value = 0;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccResult_t, Hss32GRegAccResult_hssAccAck_f, &value, &acc_mon, macro_id, 0);
    cmd = DRV_IOW(Hss32GRegAccResult_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_mon));

    /*next cr interface must interval 8ns, 1 cpu period 1.08ns*/
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");

    /*set cr invalid*/
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "write chip 0 tbl-reg  Hss32GRegAccCtl.%d  0  field hssAccValid 0\n", hss_id);
#endif

#ifdef TMG_SERDES_SIM

    mem[hss_id][reg] = data;

#endif

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_read_reg(uint8 lchip, uint16 hss_id, uint16 reg, uint16* p_data)
{
#if !defined(EMULATION_ENV) && (0 == SDK_WORK_PLATFORM)
    uint32 index    = 0;
    uint32 cmd      = 0;
    uint32 value   = 0;
    uint8  macro_id = 0;
    uint8  acc_id   = 0;
    uint32 acc_timeout = 10000;

    Hss32GRegAccCtl_m       acc_ctl;
    Hss32GRegAccResult_m    acc_mon;

    macro_id = hss_id;
    acc_id   = 0;

    index = DRV_INS(macro_id, 0);
    cmd   = DRV_IOR(Hss32GRegAccCtl_t, DRV_ENTRY_FLAG);

    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_ctl));

    /* operate read*/
    value = acc_id;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccId_f, &value, &acc_ctl, macro_id, 0);
    value = reg;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccAddr_f, &value, &acc_ctl, macro_id, 0);
    value = 1;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccIsRead_f, &value, &acc_ctl, macro_id, 0);
    value = 1;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccValid_f, &value, &acc_ctl, macro_id, 0);

    cmd   = DRV_IOW(Hss32GRegAccCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_ctl));


    /*polling acc ack*/
    cmd = DRV_IOR(Hss32GRegAccResult_t, DRV_ENTRY_FLAG);

    for(acc_timeout = 10000; acc_timeout > 0; acc_timeout--)
    {
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_mon));
        DRV_IOR_FIELD(lchip, Hss32GRegAccResult_t, Hss32GRegAccResult_hssAccAck_f, &value, &acc_mon);
        if(value != 0)
        {
            DRV_IOR_FIELD(lchip, Hss32GRegAccResult_t, Hss32GRegAccResult_hssAccAckData_f, &value, &acc_mon);
            SYS_USW_VALID_PTR_WRITE(p_data, value);
            break;
        }
    }

    /* clear acc ack*/

    value = 0;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccResult_t, Hss32GRegAccResult_hssAccAck_f, &value, &acc_mon, macro_id, 0);
    cmd = DRV_IOW(Hss32GRegAccResult_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_mon));

    if(0 == acc_timeout)
    {
        return CTC_E_HW_FAIL;
    }

    (void)_sys_tmg_serdes_wait_ms(1);

#elif defined(TMG_SERDES_SIM)

    SYS_USW_VALID_PTR_WRITE(p_data, mem[hss_id][reg]);

#endif

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_read_reg_field(uint8 lchip, uint16 serdes_id, _sys_tmg_serdes_field_t* p_field_info, uint16* p_data)
{
    uint16 reg = 0;
    uint16 reg_val = 0;
    uint8  hss_id  = 0;

    hss_id = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);

    TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, reg);
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg(lchip, hss_id, reg, &reg_val));

    *p_data = (reg_val & p_field_info->mask) >> p_field_info->lo_bit;

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_group_reg(uint8 lchip, uint16 grp, uint32 addr, uint32 mask, uint32 data)
{
    uint16 reg_val = 0;
    uint8  lo_bit  = 0;
    uint32 tmp_mask = mask;

    SYS_CONDITION_RETURN((0 == mask), CTC_E_NONE);
    
    while(!CTC_IS_BIT_SET(tmp_mask, 0))
    {
        tmp_mask = tmp_mask >> 1;
        lo_bit ++;
    }
    
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg(lchip, grp, addr, &reg_val));   
    reg_val = (reg_val &~(mask)) | ((uint16)data << lo_bit);
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg(lchip, grp, addr, reg_val));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_lane_reg(uint8 lchip, uint16 serdes_id, uint32 addr, uint32 mask, uint32 data)
{
    uint8  hss_id  = 0;

    hss_id = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);

    CTC_ERROR_RETURN(_sys_tmg_serdes_set_group_reg(lchip, hss_id, addr, mask, data));

    return CTC_E_NONE;   
}

int32 _sys_tmg_serdes_get_group_reg(uint8 lchip, uint16 grp, uint32 addr, uint32 mask, uint32* p_data)
{
    uint16 reg_val = 0;
    uint8  lo_bit  = 0;
    uint32 tmp_mask = mask;
    
    SYS_CONDITION_RETURN((0 == mask), CTC_E_NONE);
    
    while(!CTC_IS_BIT_SET(tmp_mask, 0))
    {
        tmp_mask = tmp_mask >> 1;
        lo_bit ++;
    }
    
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg(lchip, grp, addr, &reg_val));   
    reg_val = (reg_val & mask) >> lo_bit ;

    SYS_USW_VALID_PTR_WRITE(p_data, reg_val);

    return CTC_E_NONE;   
}

int32 _sys_tmg_serdes_get_lane_reg(uint8 lchip, uint16 serdes_id, uint32 addr, uint32 mask, uint32* p_data)
{
    uint8  hss_id  = 0;

    hss_id = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);

    CTC_ERROR_RETURN(_sys_tmg_serdes_get_group_reg(lchip, hss_id, addr, mask, p_data));

    return CTC_E_NONE;   
}

int32 _sys_tmg_serdes_write_reg_field(uint8 lchip, uint16 serdes_id, _sys_tmg_serdes_field_t* p_field_info, uint16 data)
{
    uint16 reg = 0;
    uint16 reg_val = 0;
    uint8  hss_id  = 0;

    hss_id = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);

    TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, reg);
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg(lchip, hss_id, reg, &reg_val));

    reg_val = (reg_val & p_field_info->retain_mask) | (data << p_field_info->lo_bit);

    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg(lchip, hss_id, reg, reg_val));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_ref_clk_en(uint8 lchip, uint16 macro_id, uint8 ref_id, uint8 enable)
{
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = enable;

    Hss32GPllCfg_m pll_cfg;

    cmd     = DRV_IOR(Hss32GPllCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pll_cfg));

    dmps_Hss32GPllCfg_hssPllCfg_0_cfgRefClkEn_f(ref_id, fld_id);

    DRV_IOW_FIELD_NZ(lchip, Hss32GPllCfg_t, fld_id, &value, &pll_cfg, macro_id, 0);

    cmd     = DRV_IOW(Hss32GPllCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pll_cfg));

    return CTC_E_NONE;

}

int32 _sys_tmg_serdes_ref_clk_sel(uint8 lchip, uint16 macro_id, uint8 ref_sel)
{
    uint16 serdes_id    = 0;
    uint8  lane_id      = 0;
    uint32 cmd          = 0;
    uint32 index        = 0;
    uint32 fld_id       = 0;
    uint32 value        = ref_sel;

    Hss32GPerLaneCfg_m perlane_cfg;

    if(ref_sel >= TMG_SERDES_REF_SEL_TOTALCNT)
    {
        return CTC_E_INVALID_PARAM;
    }

    cmd     = DRV_IOR(Hss32GPerLaneCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    for(serdes_id = macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < (macro_id + 1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id ++)
    {
        lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);
        dmps_Hss32GPerLaneCfg_hssCfg_0_cfgRefSel_f(lane_id, fld_id);
        DRV_IOW_FIELD_NZ(lchip, Hss32GPerLaneCfg_t, fld_id, &value, &perlane_cfg, macro_id, 0);
    }

    cmd     = DRV_IOW(Hss32GPerLaneCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_cr_reset(uint8 lchip, uint16 macro_id, uint8 reset)
{

    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 value    = reset;

    Hss32GReset_m reset_cfg;

    cmd     = DRV_IOR(Hss32GReset_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &reset_cfg));

    DRV_IOW_FIELD_NZ(lchip, Hss32GReset_t, Hss32GReset_cfgPhyRegAccReset_f, &value, &reset_cfg, macro_id, 0);

    cmd     = DRV_IOW(Hss32GReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &reset_cfg));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_wrapper_reset(uint8 lchip, uint16 macro_id, uint8 reset)
{
    #if 0
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 value    = reset;

    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint8  txqm_id  = 0;
    uint8  inner_macro_id = 0;

    CtcPcsCtlCfg_m reset_cfg;
    CpuMacCtlResetCtl_m cpumac_reset;

    /* NW */
    if(macro_id < SYS_TMG_MAX_HSS_NUM)
    {
        txqm_id = macro_id / SYS_TMG_HSS_NUM_PER_TXQM;
        inner_macro_id = macro_id % SYS_TMG_HSS_NUM_PER_TXQM;
        tbl_id = CtcPcsCtlCfg_t;
        cmd    = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        index  = DRV_INS(txqm_id, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &reset_cfg));

        dmps_CtcPcsCtlCfg_resetCoreHss32GUnitWrapper0_f(inner_macro_id, fld_id);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &reset_cfg, txqm_id, 0);

        dmps_CtcPcsCtlCfg_resetCoreHss32GUnitWrapperReg0_f(inner_macro_id, fld_id);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &reset_cfg, txqm_id, 0);

        cmd    = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &reset_cfg));
    }
    /* CPUMAC */
    else
    {
        tbl_id = CpuMacCtlResetCtl_t;
        cmd    = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        index  = DRV_INS(0, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cpumac_reset));

        fld_id = CpuMacCtlResetCtl_resetHss32GUnitWrapperReg_f;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &cpumac_reset, 0, 0);

        cmd    = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cpumac_reset));
    }
#endif
    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_phy_reset(uint8 lchip, uint16 macro_id, uint8* reset)
{
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 value    = 0;

    Hss32GComCfg_m com_cfg;

    cmd     = DRV_IOR(Hss32GComCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &com_cfg));

    DRV_IOR_FIELD(lchip, Hss32GComCfg_t, Hss32GComCfg_cfgPhyReset_f, &value, &com_cfg);

    SYS_USW_VALID_PTR_WRITE(reset, (uint8)value);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_phy_reset(uint8 lchip, uint16 macro_id, uint8 reset)
{
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 value    = reset;

    Hss32GComCfg_m com_cfg;

    cmd     = DRV_IOR(Hss32GComCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &com_cfg));

    DRV_IOW_FIELD_NZ(lchip, Hss32GComCfg_t, Hss32GComCfg_cfgPhyReset_f, &value, &com_cfg, macro_id, 0);

    cmd     = DRV_IOW(Hss32GComCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &com_cfg));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_overwrite_firmware(uint8 lchip, uint16 hss_id, uint32* p_fw)
{
    uint32   fw_words         = 0;
    uint32   idx              = 0;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    fw_words = sizeof(g_tmg_serdes_fw) / (2*sizeof(uint16));

    for(idx = 0; idx < fw_words; idx++)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg(lchip, hss_id, g_tmg_serdes_fw[idx][0], g_tmg_serdes_fw[idx][1]));
    }

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_sram_ext_lt_done(uint8 lchip, uint16 hss_id, uint8 done)
{
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 value    = done;

    Hss32GComCfg_m com_cfg;

    cmd     = DRV_IOR(Hss32GComCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(hss_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &com_cfg));

    DRV_IOW_FIELD_NZ(lchip, Hss32GComCfg_t, Hss32GComCfg_cfgHssSramExtLoadDone_f, &value, &com_cfg, hss_id, 0);

    cmd     = DRV_IOW(Hss32GComCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &com_cfg));

    return CTC_E_NONE;
}

/*rst level is useless, current ip only supports lane fsm reset*/
int32 _sys_tmg_serdes_get_lane_reset(uint8 lchip, uint16 serdes_id, uint8 dir, uint8* reset)
{
    uint8  macro_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;

    Hss32GReset_m reset_cfg;

    macro_id    = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    cmd     = DRV_IOR(Hss32GReset_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &reset_cfg));

    if(dir == DMPS_RX)
    {
        dmps_Hss32GReset_resetHssL0Rx_f(lane_id, fld_id);
    }
    else
    {
        dmps_Hss32GReset_resetHssL0Tx_f(lane_id, fld_id);
    }

    DRV_IOR_FIELD(lchip, Hss32GReset_t, fld_id, &value, &reset_cfg);

    SYS_USW_VALID_PTR_WRITE(reset, value);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_lane_reset(uint8 lchip, uint16 serdes_id, uint8 dir, uint8 reset)
{
    uint8  macro_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = reset;

    Hss32GReset_m reset_cfg;

    macro_id    = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    cmd     = DRV_IOR(Hss32GReset_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &reset_cfg));

    if(dir == DMPS_RX)
    {
        dmps_Hss32GReset_resetHssL0Rx_f(lane_id, fld_id);
    }
    else
    {
        dmps_Hss32GReset_resetHssL0Tx_f(lane_id, fld_id);
    }

    DRV_IOW_FIELD_NZ(lchip, Hss32GReset_t, fld_id, &value, &reset_cfg, macro_id, 0);

    cmd     = DRV_IOW(Hss32GReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &reset_cfg));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_rx_lane_reset(uint8 lchip, uint16 serdes_id, uint8 rst_level, uint8 dir, uint8 reset)
{
    /*only support register reset & fsm_reset*/

    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, dir, reset));    

    return CTC_E_NONE;   
}

#ifdef TMG_SERDES_SIM

int32 _sys_tmg_serdes_poll_lane_lf_sigdet(uint8 lchip, uint16 serdes_id, uint32 exp_value)
{
    uint32 rx_mon_addr[SYS_TMG_MAX_HSS_NUM + 1] = {0x60248920, 0x60248b20, 0x602c8920, 0x602c8b20, 0x60348920, 0x60348b20, 0x603c8920, 0x603c8b20, 0x60448920, 0x60448b20, 0x68248920, 0x68248b20, 0x682c8920, 0x682c8b20, 0x68348920, 0x68348b20, 0x683c8920, 0x683c8b20, 0x68448920, 0x68448b20, 0x54442520};
    uint8  macro_id = 0;
    uint8  lane_id  = 0;
    uint32 fld_id   = 0;
    uint32 tbl_id   = 0;
    char   fld_str[64] = {0};
    uint32 flag     = 0;

    macro_id    = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    tbl_id = Hss32GRxMon_t;
    dmps_Hss32GRxMon_hssRxMon_0_monRxSigdetLowFreq_f(lane_id, fld_id);

    drv_usw_get_field_string_by_id(lchip, tbl_id, fld_id, fld_str);
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp,"// #polling  %-20s 0 inst %-5d entry 0 field %-20s exp_value %d\n", \
                    TABLE_NAME(lchip, tbl_id), macro_id, fld_str, exp_value); \

    if(exp_value != 0)
    {
        CTC_BIT_SET(flag, 1);
    }

    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", rx_mon_addr[macro_id] + lane_id * 4, flag, 1<<1, 1000000000);

    return CTC_E_NONE;
}

#endif


int32 _sys_tmg_serdes_poll_lane_ack(uint8 lchip, uint16 serdes_id, uint8 dir, uint32 exp_value)
{


#ifdef TMG_SERDES_SIM
    uint32 rx_mon_addr[SYS_TMG_MAX_HSS_NUM + 1] = {0x60248920, 0x60248b20, 0x602c8920, 0x602c8b20, 0x60348920, 0x60348b20, 0x603c8920, 0x603c8b20, 0x60448920, 0x60448b20, 0x68248920, 0x68248b20, 0x682c8920, 0x682c8b20, 0x68348920, 0x68348b20, 0x683c8920, 0x683c8b20, 0x68448920, 0x68448b20, 0x54442520};

    uint32 tx_mon_addr[SYS_TMG_MAX_HSS_NUM + 1] = {0x602489a0, 0x60248ba0, 0x602c89a0, 0x602c8ba0, 0x603489a0, 0x60348ba0, 0x603c89a0, 0x603c8ba0, 0x604489a0, 0x60448ba0, 0x682489a0, 0x68248ba0, 0x682c89a0, 0x682c8ba0, 0x683489a0, 0x68348ba0, 0x683c89a0, 0x683c8ba0, 0x684489a0, 0x68448ba0, 0x544425a0};
    uint32 flag = 0;

#endif

#if (!defined(EMULATION_ENV) && (0 == SDK_WORK_PLATFORM))
        uint32 index    = 0;
        uint32 cmd      = 0;
        uint32 i        = 0;
        uint32 data     = 0;
        ds_t   ds = {0};
#endif


#if defined(TMG_SERDES_SIM) || (!defined(EMULATION_ENV) && (0 == SDK_WORK_PLATFORM))
    uint8  lane_id  = 0;
    uint8  macro_id = 0;
    uint32 fld_id   = 0;
    uint32 tbl_id   = 0;

    macro_id    = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    if(DMPS_RX == dir)
    {
        tbl_id = Hss32GRxMon_t;
        dmps_Hss32GRxMon_hssRxMon_0_monRxAck_f(lane_id, fld_id);
    }
    else
    {
        tbl_id = Hss32GTxMon_t;
        dmps_Hss32GTxMon_hssTxMon_0_monTxAck_f(lane_id, fld_id);
    }

#endif

#if !defined(EMULATION_ENV) && (0 == SDK_WORK_PLATFORM)
    cmd     = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);

    for(i = 0; i < 100000; i++)
    {
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &data, &ds);
        if(data == exp_value)
        {
            return CTC_E_NONE;
        }
    }

    return CTC_E_HW_FAIL;

#elif defined(TMG_SERDES_SIM)

    char   fld_str[64] = {0};
    drv_usw_get_field_string_by_id(lchip, tbl_id, fld_id, fld_str);
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp,"// #polling  %-20s 0 inst %-5d entry 0 field %-20s exp_value %d\n", \
                    TABLE_NAME(lchip, tbl_id), macro_id, fld_str, exp_value); \
    if(DMPS_RX == dir)
    {
        if(exp_value !=0)
        {
            CTC_BIT_SET(flag, 31);
        }
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", rx_mon_addr[macro_id] + lane_id * 4, flag, 1<<31, 1000000000);
    }
    else
    {
        if(exp_value !=0)
        {
            CTC_BIT_SET(flag, 2*lane_id+1);
        }
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", tx_mon_addr[macro_id], flag, 1<<(2*lane_id+1), 1000000000);
    }

#endif

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_lane_req(uint8 lchip, uint16 serdes_id, uint8 dir, uint32 enable)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;

    ds_t   ds = {0};

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    if(dir == DMPS_RX)
    {
        tbl_id  = Hss32GRxPerLaneCfg_t;
        dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxReq_f(lane_id, fld_id);
    }
    else
    {
        tbl_id  = Hss32GTxPerLaneCfg_t;
        dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxReq_f(lane_id, fld_id);
    }

    cmd     = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(hss_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

    value = enable;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &ds, hss_id, 0);

    cmd     = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_lane_power(uint8 lchip, uint16 serdes_id, uint8 dir, uint8* state)
{
    uint8  macro_id = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;

    ds_t   ds = {0};

    macro_id    = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    if(dir == DMPS_RX)
    {
        tbl_id  = Hss32GRxPerLaneCfg_t;
        dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxPstate_f(lane_id, fld_id);
    }
    else
    {
        tbl_id  = Hss32GTxPerLaneCfg_t;
        dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxPstate_f(lane_id, fld_id);
    }

    cmd     = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &ds);

    SYS_USW_VALID_PTR_WRITE(state, (uint8)value);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_lane_power(uint8 lchip, uint16 serdes_id, uint8 dir, uint8 state)
{
    uint8  macro_id = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;

    ds_t   ds = {0};

    macro_id    = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    if(dir == DMPS_RX)
    {
        tbl_id  = Hss32GRxPerLaneCfg_t;
        dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxPstate_f(lane_id, fld_id);
    }
    else
    {
        tbl_id  = Hss32GTxPerLaneCfg_t;
        dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxPstate_f(lane_id, fld_id);
    }

    cmd     = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

    value = state;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &ds, macro_id, 0);

    cmd     = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
#ifdef TMG_SERDES_SIM
            SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
#endif
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip,  serdes_id, dir, TRUE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, dir, 1));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip,  serdes_id, dir, FALSE));

#ifdef TMG_SERDES_SIM
            SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 150\n");
#endif

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_poll_sram_initdone(uint8 lchip, uint16 hss_id, uint32 exp_value)
{
#ifdef TMG_SERDES_SIM
    uint32 misc_mon_addr[SYS_TMG_MAX_HSS_NUM + 1] = {0x602489a4, 0x60248ba4, 0x602c89a4, 0x602c8ba4, 0x603489a4, 0x60348ba4, 0x603c89a4, 0x603c8ba4, 0x604489a4, 0x60448ba4, 0x682489a4, 0x68248ba4, 0x682c89a4, 0x682c8ba4, 0x683489a4, 0x68348ba4, 0x683c89a4, 0x683c8ba4, 0x684489a4, 0x68448ba4, 0x544425a4};
    uint32 flag = 0;
#endif

#if !defined(EMULATION_ENV) && (0 == SDK_WORK_PLATFORM)
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 i        = 0;
    uint32 data     = 0;
    Hss32GMiscMon_m misc_mon;
#endif

#if defined(TMG_SERDES_SIM) || (!defined(EMULATION_ENV) && (0 == SDK_WORK_PLATFORM))
    uint32 fld_id   = 0;
    uint32 tbl_id   = 0;
    uint8  macro_id = 0;

    tbl_id      = Hss32GMiscMon_t;
    fld_id      = Hss32GMiscMon_monHssSramInitDone_f;
    macro_id    = hss_id;

#endif

#if !defined(EMULATION_ENV) && (0 == SDK_WORK_PLATFORM)
    cmd     = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);

    for(i = 0; i < 100000; i++)
    {
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &misc_mon));
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &data, &misc_mon);
        if(data == exp_value)
        {
            return CTC_E_NONE;
        }
    }

    return CTC_E_HW_FAIL;

#elif defined(TMG_SERDES_SIM)

    char   fld_str[64] = {0};
    drv_usw_get_field_string_by_id(lchip, tbl_id, fld_id, fld_str);
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp,"// #polling  %-20s 0 inst %-5d entry 0 field %-20s exp_value %d\n", \
                    TABLE_NAME(lchip, tbl_id), macro_id, fld_str, exp_value); \

    if(exp_value != 0)
    {
        CTC_BIT_SET(flag, 7);
    }

    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", misc_mon_addr[macro_id], flag, 1<<7, 1000000000);

#endif

    return CTC_E_NONE;

}

int32 _sys_tmg_serdes_get_datapath_en(uint8 lchip, uint16 serdes_id, uint8 dir, uint8* enable)
{
    uint8  macro_id = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;

    ds_t   ds = {0};

    macro_id    = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    if(dir == DMPS_RX)
    {
        tbl_id  = Hss32GRxPerLaneCfg_t;
        dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxDataEn_f(lane_id, fld_id);
    }
    else
    {
        tbl_id  = Hss32GTxPerLaneCfg_t;
        dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxDataEn_f(lane_id, fld_id);
    }

    cmd     = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &ds);

    SYS_USW_VALID_PTR_WRITE(enable, (uint8)value);    

    return CTC_E_NONE;    
}

int32 _sys_tmg_serdes_set_datapath_en(uint8 lchip, uint16 serdes_id, uint8 dir, uint8 enable)
{
    uint8  macro_id = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;

    ds_t   ds = {0};

    macro_id    = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    if(dir == DMPS_RX)
    {
        tbl_id  = Hss32GRxPerLaneCfg_t;
        dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxDataEn_f(lane_id, fld_id);
    }
    else
    {
        tbl_id  = Hss32GTxPerLaneCfg_t;
        dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxDataEn_f(lane_id, fld_id);
    }

    cmd     = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

    value = enable;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &ds, macro_id, 0);

    cmd     = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
#ifdef TMG_SERDES_SIM
            SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
#endif
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip,  serdes_id, dir, TRUE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, dir, 1));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip,  serdes_id, dir, FALSE));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_anlt_reset(uint8 lchip, uint16 serdes_id, uint8 dir, uint8 reset)
{
    uint8  macro_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;

    Hss32GReset_m reset_cfg;

    macro_id    = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    if(dir == DMPS_RX)
    {
        tbl_id  = Hss32GReset_t;
        dmps_Hss32GReset_cfgL0AnltRxReset_f(lane_id, fld_id);
    }
    else
    {
        tbl_id  = Hss32GReset_t;
        dmps_Hss32GReset_cfgL0AnltTxReset_f(lane_id, fld_id);
    }

    cmd     = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &reset_cfg));

    value = reset;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &reset_cfg, macro_id, 0);

    cmd     = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &reset_cfg));

    return CTC_E_NONE;
}

/*TBD*/
int32 _sys_tmg_serdes_set_txclk_ready(uint8 lchip, uint16 serdes_id, uint8 enable)
{
    uint16 macro_id      = 0;
    uint8  lane_id      = 0;
    uint32 cmd          = 0;
    uint32 index        = 0;
    uint32 tbl_id       = 0;
    uint32 fld_id       = 0;
    uint32 value        = 0;

    Hss32GComCfg_m com_cfg;

    macro_id    = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    tbl_id  = Hss32GComCfg_t;
    cmd     = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &com_cfg));

    dmps_Hss32GComCfg_cfgHssL0TxClkReady_f(lane_id, fld_id);
    value = enable;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &com_cfg, macro_id, 0);

    cmd     = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &com_cfg));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_lane_prbs_test_en(uint8 lchip, uint16 serdes_id, uint8 dir, uint8 en)
{
    /*prbs is enabled once internal type reg is none-zero val, refer to type api*/
    if(!en)
    {
        if(DMPS_RX == dir)
        {
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_PRBS_MODE), TMG_SERDES_PAT_DISABLE));
        }
        else
        {
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_TX_PRBS_MODE), TMG_SERDES_PAT_DISABLE));       
        }
    }
    
    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_tx_eq_force(uint8 lchip, uint16 serdes_id, void* p_data)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = 0;
    
    ctc_chip_serdes_ffe_t* p_ffe = (ctc_chip_serdes_ffe_t*)p_data;

    Hss32GTxPerLaneCfg_m perlane_cfg;

    if(p_ffe->coefficient[0] > TMG_TXFFE_PRE_MAX)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " C0 out of bound, max %u!\n", TMG_TXFFE_PRE_MAX);
            return CTC_E_INVALID_CONFIG;
    }

    if(p_ffe->coefficient[1] > TMG_TXFFE_MAIN_MAX)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " C1 out of bound, max %u!\n", TMG_TXFFE_MAIN_MAX);
            return CTC_E_INVALID_CONFIG;
    }

    if(p_ffe->coefficient[2] > TMG_TXFFE_POST_MAX)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " C2 out of bound, max %u!\n", TMG_TXFFE_POST_MAX);
            return CTC_E_INVALID_CONFIG;
    }

    /* delete full swing constrain, configure by user */
#if 0
    if(p_ffe->coefficient[0] + p_ffe->coefficient[1] * 4 + p_ffe->coefficient[2] > TMG_TXFFE_FULL_SWING)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " |C0| + 4 * C1 + |C2| out of bound, max %u!\n", TMG_TXFFE_FULL_SWING);
            return CTC_E_INVALID_CONFIG;
    }
#endif

    serdes_id   = p_ffe->serdes_id;
    hss_id      = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    tbl_id = Hss32GTxPerLaneCfg_t;
    cmd    = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index  = DRV_INS(hss_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxEqPre_f(lane_id, fld_id);
    value   = p_ffe->coefficient[0];
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxEqMain_f(lane_id, fld_id);
    value   = p_ffe->coefficient[1];
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxEqPost_f(lane_id, fld_id);
    value   = p_ffe->coefficient[2];
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

    cmd    = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    index  = DRV_INS(hss_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_lane_fw_sts(uint8 lchip, uint16 serdes_id, uint8* p_stat)
{
    uint16 value = 0;
    
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_FW_MEM_ADDR_MON), &value));

    SYS_USW_VALID_PTR_WRITE(p_stat, (uint8)(value & 0xff));

    return CTC_E_NONE;   
}

int32 _sys_tmg_serdes_get_group_fw_version(uint8 lchip, uint16 hss_id, void* p_value)
{
    uint16 value     = 0;
    uint16 serdes_id = SYS_TMG_LANE_NUM_PER_HSS * hss_id;

    sys_usw_dmps_serdes_fw_version_t* p_version = (sys_usw_dmps_serdes_fw_version_t*)p_value;
    
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_FW_VERSION_A), &value));
    p_version->v_major = value;

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_FW_VERSION_B), &value));
    p_version->v_minor = value;

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_FW_VERSION_C), &value));
    p_version->v_patch = value;

    return CTC_E_NONE;
}

int32 sys_tmg_serdes_get_fw_version(uint8 lchip, void* p_value)
{
#ifndef EMULATION_ENV
    uint8 find_flag     = FALSE;
    uint8 hss_id        = 0;
    uint8 macro_id      = 0;
    uint16 serdes_base  = 0;
    uint16 serdes_id    = 0;
    uint16 txqm_id      = 0;
    int32  ret          = 0;
    sys_usw_dmps_serdes_fw_version_t* p_version = (sys_usw_dmps_serdes_fw_version_t*)p_value;

    for(macro_id = 0; macro_id < SYS_TMG_MAC_GROUP_NUM; macro_id++)
    {
        serdes_base  = macro_id * SYS_TMG_LANE_NUM_PER_HSS;
        txqm_id = SYS_TMG_GET_TXQM_BY_MAC_ID(serdes_base);
        if (!_sys_tmg_mac_is_power_up(lchip, txqm_id))
        {
            continue;
        }
        for(serdes_id = serdes_base; serdes_id < serdes_base + SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            hss_id = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
            ret = _sys_tmg_serdes_get_group_fw_version(lchip, hss_id, &(p_version[0]));
            if(CTC_E_NONE == ret)
            {
                find_flag = TRUE;
                break;
            }
        }
        if(find_flag)
        {
            break;
        }        
    }
#endif
    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_rx_train_stat(uint8 lchip, uint16 serdes_id, uint8* p_en, uint8* p_stat, uint32* p_reason)
{
    uint8  macro_id = 0;
    uint8  macro_lane_id    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 value    = 0;
    uint16 val_16;
    
    Hss32GRxMon_m rxmon;

    macro_id        = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    macro_lane_id   = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RX_ADAPT_REQ), &val_16));
    SYS_USW_VALID_PTR_WRITE(p_en, (uint8)val_16);
    
    tbl_id = Hss32GRxMon_t;
    dmps_Hss32GRxMon_hssRxMon_0_monRxAdaptAck_f(macro_lane_id, fld_id);

    cmd    = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index  = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rxmon));

    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &rxmon);
    
    SYS_USW_VALID_PTR_WRITE(p_stat,   value);
    SYS_USW_VALID_PTR_WRITE(p_reason, 0);

    return CTC_E_NONE;
}


int32 _sys_tmg_serdes_set_rx_train_en(uint8 lchip, uint16 serdes_id, uint8 enable)
{
#if 0     
    uint16 macro_id      = 0;
    uint8 lane_id       = 0;
    uint32 cmd          = 0;
    uint32 index        = 0;
    uint32 tbl_id       = 0;
    uint32 fld_id       = 0;
    uint32 value        = 0;

    Hss32GRxPerLaneCfg_m rx_cfg;

    macro_id    = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    tbl_id  = Hss32GRxPerLaneCfg_t;
    cmd     = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_cfg));

    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxAdaptReq_f(lane_id, fld_id);
    value = enable;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &rx_cfg, macro_id, 0);

    cmd     = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_cfg));
#endif

    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RX_ADAPT_REQ), (uint16)enable));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_txeq_param(uint8 lchip, uint16 serdes_id, void* p_data)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = 0;

    Hss32GTxPerLaneCfg_m perlane_cfg;
    
    ctc_chip_serdes_ffe_t* p_ffe = (ctc_chip_serdes_ffe_t*)p_data;

    hss_id      = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    tbl_id = Hss32GTxPerLaneCfg_t;
    cmd    = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index  = DRV_INS(hss_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxEqPre_f(lane_id, fld_id);
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &perlane_cfg);
    p_ffe->coefficient[0] = (uint16)value;

    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxEqMain_f(lane_id, fld_id);
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &perlane_cfg);
    p_ffe->coefficient[1] = (uint16)value;

    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxEqPost_f(lane_id, fld_id);
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &perlane_cfg);
    p_ffe->coefficient[2] = (uint16)value;

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_lane_polarity(uint8 lchip, uint16 serdes_id, uint8 dir, uint8 pol)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = 0;

    ds_t ds = {0};

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    if(DMPS_RX == dir)
    {
        tbl_id = Hss32GRxPerLaneCfg_t;
        dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxInvert_f(lane_id, fld_id);
    }
    else
    {
        tbl_id = Hss32GTxPerLaneCfg_t;
        dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxInvert_f(lane_id, fld_id);
    }

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

    value = pol;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &ds, hss_id, 0);

    cmd   = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_group_power(uint8 lchip, uint16 hss_id, uint8* p_value)
{
    uint8 phy_reset = 0;

    CTC_ERROR_RETURN(_sys_tmg_serdes_get_phy_reset(lchip, hss_id, &phy_reset));

    SYS_USW_VALID_PTR_WRITE(p_value, !phy_reset);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_lane_polarity(uint8 lchip, uint16 serdes_id, uint8 dir, uint8* p_pol)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = 0;
    ds_t   ds = {0};

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    if(DMPS_RX == dir)
    {
        tbl_id = Hss32GRxPerLaneCfg_t;
        dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxInvert_f(lane_id, fld_id);
    }
    else
    {
        tbl_id = Hss32GTxPerLaneCfg_t;
        dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxInvert_f(lane_id, fld_id);
    }

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &ds);

    SYS_USW_VALID_PTR_WRITE(p_pol, (uint8)(value ? DMPS_POLARITY_INV : DMPS_POLARITY_NORM));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_lane_loopback(uint8 lchip, uint16 serdes_id, void* p_data)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = 0;

    Hss32GPerLaneCfg_m perlane_cfg;
    Hss32GMacroCfg_m   macro_cfg;

    ctc_chip_serdes_loopback_t* p_loopback = (ctc_chip_serdes_loopback_t*)p_data;
    CTC_PTR_VALID_CHECK(p_loopback);

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);

    tbl_id = Hss32GPerLaneCfg_t;
    cmd    = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    tbl_id = Hss32GMacroCfg_t;
    cmd    = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macro_cfg));

    if(FALSE == p_loopback->enable)
    {
        tbl_id = Hss32GPerLaneCfg_t;
        dmps_Hss32GPerLaneCfg_hssCfg_0_cfgParallelLpbkEn_f(lane_id, fld_id);
        value  = 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

        dmps_Hss32GPerLaneCfg_hssCfg_0_cfgInternalLpbkEn_f(lane_id, fld_id);
        value  = 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

        tbl_id = Hss32GMacroCfg_t;
        dmps_Hss32GMacroCfg_cfgPcsL0LpbkEn_f(lane_id, fld_id);
        value  = 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &macro_cfg, hss_id, 0);

#ifndef EMULATION_ENV
        dmps_Hss32GMacroCfg_cfgHssL0ForceSigDet_f(lane_id, fld_id);
        value  = 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &macro_cfg, hss_id, 0);
#endif
    }
    else
    {
        switch(p_loopback->mode)
        {
            /* Local digital loopback*/
            case DMPS_SERDES_LPBK_LOCAL:

                tbl_id = Hss32GPerLaneCfg_t;
                dmps_Hss32GPerLaneCfg_hssCfg_0_cfgParallelLpbkEn_f(lane_id, fld_id);
                value  = 0;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

                dmps_Hss32GPerLaneCfg_hssCfg_0_cfgInternalLpbkEn_f(lane_id, fld_id);
                value  = 0;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

                tbl_id = Hss32GMacroCfg_t;
                dmps_Hss32GMacroCfg_cfgPcsL0LpbkEn_f(lane_id, fld_id);
                value  = 1;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &macro_cfg, hss_id, 0);

                dmps_Hss32GMacroCfg_cfgHssL0ForceSigDet_f(lane_id, fld_id);
                value  = 1;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &macro_cfg, hss_id, 0);

                break;

            /* External loopback*/
            case DMPS_SERDES_LPBK_EXTERNAL:

                tbl_id = Hss32GPerLaneCfg_t;
                dmps_Hss32GPerLaneCfg_hssCfg_0_cfgParallelLpbkEn_f(lane_id, fld_id);
                value  = 1;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

                dmps_Hss32GPerLaneCfg_hssCfg_0_cfgInternalLpbkEn_f(lane_id, fld_id);
                value  = 0;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

                tbl_id = Hss32GMacroCfg_t;
                dmps_Hss32GMacroCfg_cfgPcsL0LpbkEn_f(lane_id, fld_id);
                value  = 0;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &macro_cfg, hss_id, 0);

                dmps_Hss32GMacroCfg_cfgHssL0ForceSigDet_f(lane_id, fld_id);
                value  = 0;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &macro_cfg, hss_id, 0);

                break;

            /* Internal analog loopback*/
            /* TODO: tx clock uses rx clock , cfg tx rate to 0*/
            case DMPS_SERDES_LPBK_INTERNAL:

                tbl_id = Hss32GPerLaneCfg_t;
                dmps_Hss32GPerLaneCfg_hssCfg_0_cfgParallelLpbkEn_f(lane_id, fld_id);
                value  = 0;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

                dmps_Hss32GPerLaneCfg_hssCfg_0_cfgInternalLpbkEn_f(lane_id, fld_id);
                value  = 1;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

                tbl_id = Hss32GMacroCfg_t;
                dmps_Hss32GMacroCfg_cfgPcsL0LpbkEn_f(lane_id, fld_id);
                value  = 0;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &macro_cfg, hss_id, 0);

                dmps_Hss32GMacroCfg_cfgHssL0ForceSigDet_f(lane_id, fld_id);
                value  = 0;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &macro_cfg, hss_id, 0);

                break;
            default:
                return CTC_E_INVALID_PARAM;

        }
    }

    tbl_id = Hss32GPerLaneCfg_t;
    cmd    = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    tbl_id = Hss32GMacroCfg_t;
    cmd    = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macro_cfg));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_lane_loopback(uint8 lchip, uint16 serdes_id, void* p_data)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = 0;

    ds_t   ds       = {0};

    ctc_chip_serdes_loopback_t* p_loopback = (ctc_chip_serdes_loopback_t*)p_data;

    CTC_PTR_VALID_CHECK(p_loopback);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d, mode:%d\n", serdes_id, p_loopback->mode);

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    switch(p_loopback->mode)
    {
        case DMPS_SERDES_LPBK_LOCAL: /* Local digital Loopback */
            tbl_id = Hss32GMacroCfg_t;
            dmps_Hss32GMacroCfg_cfgPcsL0LpbkEn_f(lane_id, fld_id);
            break;
        case DMPS_SERDES_LPBK_EXTERNAL: /* External Loopback */
            tbl_id = Hss32GPerLaneCfg_t;
            dmps_Hss32GPerLaneCfg_hssCfg_0_cfgParallelLpbkEn_f(lane_id, fld_id);
            break;
        case DMPS_SERDES_LPBK_INTERNAL: /* Internal analog Loopback*/
            tbl_id = Hss32GPerLaneCfg_t;
            dmps_Hss32GPerLaneCfg_hssCfg_0_cfgInternalLpbkEn_f(lane_id, fld_id);
            break;
        default:
            p_loopback->enable = 0;
            return CTC_E_NONE;
    }

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &ds);

    p_loopback->enable = (uint8)value;

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_rx_ctle_force(uint8 lchip, uint16 serdes_id, void* p_data)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = Hss32GRxPerLaneCfg_t;
    
    Hss32GRxPerLaneCfg_m perlane_cfg;

    ctc_chip_serdes_ctle_t* p_ctle = (ctc_chip_serdes_ctle_t*)p_data;

    SYS_CONDITION_RETURN((NULL == p_ctle), CTC_E_INVALID_PTR);

    CTC_PTR_VALID_CHECK(p_ctle);
    
    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqCtleBoost_f(lane_id, fld_id);
    value   = p_ctle->value[0];
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);


    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqCtlePole_f(lane_id, fld_id);
    value   = p_ctle->value[1];
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

    cmd   = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip, serdes_id, DMPS_RX, TRUE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_RX, 0));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip, serdes_id, DMPS_RX, FALSE));
    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_rx_ctle(uint8 lchip, uint16 serdes_id, void* p_data)
{
    uint16 value    = 0;
    
    ctc_chip_serdes_ctle_t* p_ctle = (ctc_chip_serdes_ctle_t*)p_data;

    SYS_CONDITION_RETURN((NULL == p_ctle), CTC_E_INVALID_PTR);

    CTC_PTR_VALID_CHECK(p_ctle);

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_EQ_CTLE_BOOST_ASIC), &value));

    p_ctle->value[0] = (uint16)value;
    
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_EQ_CTLE_POLE_ASIC), &value));

    p_ctle->value[1] = (uint16)value;

    return CTC_E_NONE;
}

int32
_sys_tmg_serdes_prbs_type2pattern(uint8 polynome_type, uint8* p_pattern)
{
    CTC_PTR_VALID_CHECK(p_pattern);

    switch(polynome_type)
    {
        case 0:
        case 1:
            *p_pattern = TMG_SERDES_PAT_PRBS7;
            break;
        case 2:
        case 3:
            *p_pattern = TMG_SERDES_PAT_PRBS15;
            break;
        case 4:
        case 5:
            *p_pattern = TMG_SERDES_PAT_PRBS23;
            break;
        case 6:
        case 7:
            *p_pattern = TMG_SERDES_PAT_PRBS31;
            break;
        case 8:
            *p_pattern = TMG_SERDES_PAT_PRBS9;
            break;
        case 9:
            *p_pattern = TMG_SERDES_PAT_PRBS13;
            break;
        default:
            return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

int32
_sys_tmg_serdes_prbs_pattern2type(uint8 pattern, uint8* p_polynome_type)
{
    CTC_PTR_VALID_CHECK(p_polynome_type);

    switch(pattern)
    {
        case TMG_SERDES_PAT_PRBS7:
            *p_polynome_type = CTC_CHIP_SERDES_PRBS7_PLUS;
            break;
        case TMG_SERDES_PAT_PRBS15:
            *p_polynome_type = CTC_CHIP_SERDES_PRBS15_PLUS;
            break;
        case TMG_SERDES_PAT_PRBS23:
            *p_polynome_type = CTC_CHIP_SERDES_PRBS23_PLUS;
            break;
        case TMG_SERDES_PAT_PRBS31:
            *p_polynome_type = CTC_CHIP_SERDES_PRBS31_PLUS;
            break;
        case TMG_SERDES_PAT_PRBS9:
            /*REFER TO ctc_chip_serdes_prbs_polynome_e , dont exist prbs9 */
            *p_polynome_type = 8;
            break;
        case TMG_SERDES_PAT_PRBS13:
            /*REFER TO ctc_chip_serdes_prbs_polynome_e , dont exist prbs13 */
            *p_polynome_type = 9;
            break;
        default:
            return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

int32
_sys_tmg_serdes_get_tx_prbs(uint8 lchip, ctc_chip_serdes_prbs_t *p_prbs)
{
    uint16 value;
    uint8  type;
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, p_prbs->serdes_id, REG_STR(TMG_SERDES_TX_PRBS_MODE), &value));

    if(TMG_SERDES_PAT_DISABLE == value)
    {
        p_prbs->value = 0;
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_prbs_pattern2type((uint8)value, &type));
        p_prbs->value = 1;
        p_prbs->polynome_type = type;
    }

    return CTC_E_NONE;
}

int32
_sys_tmg_serdes_set_tx_prbs(uint8 lchip, ctc_chip_serdes_prbs_t *p_prbs)
{
    uint8 pattern = 0;
    uint32 value  = 0;

    if(1 == p_prbs->value)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_prbs_type2pattern(p_prbs->polynome_type, &pattern));
        value = pattern;
    }
    else
    {
        value = TMG_SERDES_PAT_DISABLE;
    }

    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, p_prbs->serdes_id, REG_STR(TMG_SERDES_TX_PRBS_MODE), value));

    return CTC_E_NONE;
}

int32
_sys_tmg_serdes_get_lane_prbs_test_cnt(uint8 lchip, uint16 serdes_id, void* p_data)
{
    uint16 ov14     = 0;
    uint16 count    = 0;
    ctc_chip_serdes_prbs_t* p_prbs = (ctc_chip_serdes_prbs_t*)p_data;

    CTC_PTR_VALID_CHECK(p_data);

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_PRBS_OV14), &ov14));
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_PRBS_COUNT), &count));

    if(ov14 == 1)
    {
        count = count << 7;
    }

    p_prbs->error_cnt = count;

    return CTC_E_NONE;
}

int32
_sys_tmg_serdes_set_prbs_cnt_rst(uint8 lchip, uint16 serdes_id)
{
    /* for reliable operation , toggle sync twice*/
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_PRBS_SYNC), TRUE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_PRBS_SYNC), TRUE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_PRBS_SYNC), FALSE));

    return CTC_E_NONE;
}

int32 
_sys_tmg_serdes_set_lane_prbs_test_run(uint8 lchip, uint16 serdes_id, uint32 duration_ms, void* p_data)
{
    //uint8 pattern = 0;
    uint16 value = 0;

    ctc_chip_serdes_prbs_t* p_prbs = (ctc_chip_serdes_prbs_t*) p_data;

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d, value:%d, type:%d, mode:%d\n", p_prbs->serdes_id, p_prbs->value, p_prbs->polynome_type, p_prbs->mode);

#if 0 
    /*step 1. set prbs rx pattern*/
    CTC_ERROR_RETURN(_sys_tmg_serdes_prbs_type2pattern(p_prbs->polynome_type, &pattern));
    value = pattern;
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_PRBS_MODE), value));
#endif

    /*step 2. reset prbs counter*/
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_prbs_cnt_rst(lchip, serdes_id));

    /*step 3. wait and get counter*/
    sal_task_sleep(duration_ms);
    p_prbs->value = 1;
    CTC_ERROR_RETURN(_sys_tmg_serdes_get_lane_prbs_test_cnt(lchip, serdes_id, (void*)p_prbs));

    if(0 != p_prbs->error_cnt)
    {
        p_prbs->value = 0;
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%% PRBS chek status error! err_cnt = %u\n", p_prbs->error_cnt);
    }

    /*step 4. disable prbs check*/
    value = TMG_SERDES_PAT_DISABLE;
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_PRBS_MODE), value));

    return CTC_E_NONE;

}


int32 _sys_tmg_serdes_set_rx_prbs_check(uint8 lchip, ctc_chip_serdes_prbs_t *p_prbs)
{
    uint16 serdes_id = 0;
    uint8 pattern = 0;
    uint16 value = 0;

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d, value:%d, type:%d, mode:%d\n", p_prbs->serdes_id, p_prbs->value, p_prbs->polynome_type, p_prbs->mode);

    serdes_id = p_prbs->serdes_id;

    /*step 1. set prbs rx pattern*/
    CTC_ERROR_RETURN(_sys_tmg_serdes_prbs_type2pattern(p_prbs->polynome_type, &pattern));
    value = pattern;
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_PRBS_MODE), value));

    /*step 2. reset prbs counter*/
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_prbs_cnt_rst(lchip, serdes_id));

    /*step 3. wait and get counter*/
    sal_task_sleep(1000);
    p_prbs->value = 1;
    CTC_ERROR_RETURN(_sys_tmg_serdes_get_lane_prbs_test_cnt(lchip, serdes_id, (void*)p_prbs));

    if(0 != p_prbs->error_cnt)
    {
        p_prbs->value = 0;
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%% PRBS chek status error! err_cnt = %u\n", p_prbs->error_cnt);
    }

    /*step 4. disable prbs check*/
    value = TMG_SERDES_PAT_DISABLE;
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_PRBS_MODE), value));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_pcs_prbs_en(uint8 lchip, uint16 serdes_id, uint8 enable)
{
    uint8  macro_id     = 0;
    uint8  lane_id      = 0;
    uint32 cmd          = 0;
    uint32 index        = 0;
    uint32 fld_id       = 0;
    uint32 value        = enable;

    Hss32GReset_m reset;

    macro_id = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);

    cmd     = DRV_IOR(Hss32GReset_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &reset));

    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);
    dmps_Hss32GReset_cfgHssL0TxPrbsEn_f(lane_id, fld_id);
    DRV_IOW_FIELD_NZ(lchip, Hss32GReset_t, fld_id, &value, &reset, macro_id, 0);

    cmd     = DRV_IOW(Hss32GReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &reset));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_lane_prbs_test_pattern(uint8 lchip, uint16 serdes_id, uint8 dir, uint8 poly_type)
{
    uint16 value = 0;
    uint8  pattern = 0;

    CTC_ERROR_RETURN(_sys_tmg_serdes_prbs_type2pattern(poly_type, &pattern));
    value = pattern;

    if(DMPS_RX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_PRBS_MODE), value));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_TX_PRBS_MODE), value));       
    }

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_lane_prbs_test_pattern(uint8 lchip, uint16 serdes_id, uint8 dir, uint8* p_poly_type)
{
    uint16 value   = 0;
    uint8  pattern = 0;
    
    CTC_PTR_VALID_CHECK(p_poly_type);

    if(DMPS_RX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_PRBS_MODE), &value));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_TX_PRBS_MODE), &value));       
    }

    pattern = (uint8)value;

    CTC_ERROR_RETURN(_sys_tmg_serdes_prbs_pattern2type(pattern, p_poly_type));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_lane_prbs_test_en(uint8 lchip, uint16 serdes_id, uint8 dir, uint8* p_en)
{
    uint16 value = 0;

    CTC_PTR_VALID_CHECK(p_en);

    if(DMPS_RX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_PRBS_MODE), &value));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_TX_PRBS_MODE), &value));
    }

    *p_en = (uint8)value ? 1: 0;

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_prbs(uint8 lchip, void* p_data)
{
    ctc_chip_serdes_prbs_t* p_prbs = (ctc_chip_serdes_prbs_t*)p_data;
    CTC_PTR_VALID_CHECK(p_prbs);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d, mode:%u\n", p_prbs->serdes_id, p_prbs->mode);

    switch(p_prbs->mode)
    {
        case 0: /* 0--Rx */
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_rx_prbs_check(lchip, p_prbs));
            break;
        case 1: /* 1--Tx */
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_prbs(lchip, p_prbs));
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_prbs(uint8 lchip, void* p_data)
{
    ctc_chip_serdes_prbs_t* p_prbs = (ctc_chip_serdes_prbs_t*)p_data;
    CTC_PTR_VALID_CHECK(p_prbs);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d, mode:%u\n", p_prbs->serdes_id, p_prbs->mode);

    switch(p_prbs->mode)
    {
        case 0: /* 0--Rx */
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "get prbs rx information, must close link monitor thread\n");
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_rx_prbs_check(lchip, p_prbs));
            break;
        case 1: /* 1--Tx */
            CTC_ERROR_RETURN(_sys_tmg_serdes_get_tx_prbs(lchip, p_prbs));
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_margin_set_param(uint8 lchip, uint16 serdes_id, sys_tmg_serdes_margin_param_t* p_param)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = Hss32GRxPerLaneCfg_t;
    uint16 margin_vdac  = p_param->margin_vdac;
    uint8  margin_iq    = p_param->margin_iq;
    uint8  clear        = p_param->clear;
    uint8  enable       = p_param->enable;

    Hss32GRxPerLaneCfg_m perlane_cfg;

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxMarginVdac_f(lane_id, fld_id);
    value   = margin_vdac;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);


    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxMarginIq_f(lane_id, fld_id);
    value   = margin_iq;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);


    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxMarginErrClr_f(lane_id, fld_id);
    value   = clear;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxMarginInProg_f(lane_id, fld_id);
    value   = enable;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

    cmd   = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip, serdes_id, DMPS_RX, TRUE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_RX, 0));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip, serdes_id, DMPS_RX, FALSE));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_margin_get_error_cnt(uint8 lchip, uint16 serdes_id, uint8* p_err_cnt)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = Hss32GRxMon_t;

    Hss32GRxMon_m rx_mon;

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_mon));

    dmps_Hss32GRxMon_hssRxMon_0_monRxMarginErr_f(lane_id, fld_id);

    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &rx_mon);

    SYS_USW_VALID_PTR_WRITE(p_err_cnt, (uint8)value);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_eye_margin(uint8 lchip, uint16 serdes_id, uint8 wh_flag, uint32 *eye_margin)
{
    uint8 err_cnt = 0;
    int32 phase = 0;
    int32 volt = 0;
    int32 left = 0;
    int32 right = 0;
    int32 upper = 0;
    int32 lower = 0;
    int32 max_phase = 0;
    int32 min_phase = 0;
    int32 max_volt = 0;
    int32 min_volt = 0;
    uint16 phase_cnt = 0;
    uint16 volt_cnt = 0;

    sys_tmg_serdes_margin_param_t margin = {0};

    margin.margin_iq = 0;
    margin.margin_vdac = 0;
    margin.enable = TRUE;
    margin.clear  = TRUE;

    volt_cnt    = SYS_TMG_SERDES_MARGIN_VOLT_CNT;
    phase_cnt   = SYS_TMG_SERDES_MARGIN_PHASE_CNT;

    max_volt    = volt_cnt - 1;
    min_volt    = -volt_cnt;
    max_phase   = phase_cnt -1;
    min_phase   = -phase_cnt;

    /* Set default edge values */
    upper = max_volt;
    lower = min_volt;
    left  = max_phase;
    right = min_phase;

    if(SYS_TMG_SERDES_EYE_HEIGHT == wh_flag)
    {
        /* scan upper */
        for(volt = 0; volt <= max_volt; volt++)
        {
            margin.margin_iq    = 0;
            margin.margin_vdac  = volt;
            CTC_ERROR_RETURN(_sys_tmg_serdes_margin_set_param(lchip, serdes_id, &margin));
            CTC_ERROR_RETURN(_sys_tmg_serdes_margin_get_error_cnt(lchip, serdes_id, &err_cnt));

            /* Update once when error */
            if(err_cnt > 0)
            {
                upper = volt;
            }
        }

        /* scan upper */
        for(volt = 0; volt >= min_volt; volt--)
        {
            margin.margin_iq    = 0;
            margin.margin_vdac  = volt;
            CTC_ERROR_RETURN(_sys_tmg_serdes_margin_set_param(lchip, serdes_id, &margin));
            CTC_ERROR_RETURN(_sys_tmg_serdes_margin_get_error_cnt(lchip, serdes_id, &err_cnt));

            /* Update once when error */
            if(err_cnt > 0)
            {
                lower = volt;
            }
        }

        margin.enable    = FALSE;
        CTC_ERROR_RETURN(_sys_tmg_serdes_margin_set_param(lchip, serdes_id, &margin));

        SYS_USW_VALID_PTR_WRITE(eye_margin, (uint32)(upper - lower));
    }
    else
    {

        /* scan left */
        for(phase = 0; phase <= max_phase; phase++)
        {
            margin.margin_iq    = phase;
            margin.margin_vdac  = 0;
            CTC_ERROR_RETURN(_sys_tmg_serdes_margin_set_param(lchip, serdes_id, &margin));
            CTC_ERROR_RETURN(_sys_tmg_serdes_margin_get_error_cnt(lchip, serdes_id, &err_cnt));

            /* Update once when error */
            if(err_cnt > 0)
            {
                left = phase;
            }
        }

        /* scan right */
        for(phase = 0; phase >= min_phase; phase--)
        {
            margin.margin_iq    = phase;
            margin.margin_vdac  = 0;
            CTC_ERROR_RETURN(_sys_tmg_serdes_margin_set_param(lchip, serdes_id, &margin));
            CTC_ERROR_RETURN(_sys_tmg_serdes_margin_get_error_cnt(lchip, serdes_id, &err_cnt));

            /* Update once when error */
            if(err_cnt > 0)
            {
                right = phase;
            }
        }

        margin.enable    = FALSE;
        CTC_ERROR_RETURN(_sys_tmg_serdes_margin_set_param(lchip, serdes_id, &margin));

        SYS_USW_VALID_PTR_WRITE(eye_margin, (uint32)(left - right));
    }

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_rx_eye_open(uint8 lchip, uint16 serdes_id, uint8 wh_sel, uint32* p_eo_margin)
{

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d  wh_sel:%d\n", serdes_id, wh_sel);

    if(DMPS_SERDES_EYE_WIDTH == wh_sel)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_get_eye_margin(lchip, serdes_id, SYS_TMG_SERDES_EYE_WIDTH, p_eo_margin));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_get_eye_margin(lchip, serdes_id, SYS_TMG_SERDES_EYE_HEIGHT, p_eo_margin));
    }

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_rx_eye_plot(uint8 lchip, uint16 serdes_id, uint32* p_eye_data)
{
    int32 ret = CTC_E_NONE;
    uint8 err_cnt = 0;
    int32 phase = 0;
    int32 volt = 0;
    int32 max_phase = 0;
    int32 min_phase = 0;
    int32 max_volt = 0;
    int32 min_volt = 0;
    uint16 phase_cnt = 0;
    uint16 volt_cnt = 0;
    uint16 p_max    = 0;
    uint16 v_max    = 0;
    uint32 num  = 0;
    char* eye_lv = NULL;

    sys_tmg_serdes_margin_param_t margin = {0};

    margin.margin_iq = 0;
    margin.margin_vdac = 0;
    margin.enable = TRUE;
    margin.clear  = TRUE;

    volt_cnt    = SYS_TMG_SERDES_MARGIN_VOLT_CNT;
    phase_cnt   = SYS_TMG_SERDES_MARGIN_PHASE_CNT;

    max_volt    = volt_cnt - 1;
    min_volt    = -volt_cnt;
    max_phase   = phase_cnt -1;
    min_phase   = -phase_cnt;

    p_max       = 2 * phase_cnt;
    v_max       = 2 * volt_cnt;

    num = p_max * v_max;
    eye_lv = (char*)mem_malloc(MEM_DMPS_MODULE, num * sizeof(char));
    if(NULL == eye_lv)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(eye_lv, DMPS_INVALID_VALUE_U8, num * sizeof(uint8));

    for(volt = min_volt; volt <= max_volt; volt++)
    {
        for(phase = min_phase; phase <= max_phase; phase++)
        {
            margin.margin_iq    = phase;
            margin.margin_vdac  = volt;
            CTC_ERROR_GOTO(_sys_tmg_serdes_margin_set_param(lchip, serdes_id, &margin),
                ret, RELEASE_PTR_RETURN);
            CTC_ERROR_GOTO(_sys_tmg_serdes_margin_get_error_cnt(lchip, serdes_id, &err_cnt),
                ret, RELEASE_PTR_RETURN);

            eye_lv[p_max *(volt_cnt - volt) + phase + phase_cnt] = (err_cnt == 0) ? ' ' : '*';

        }
    }

    margin.enable    = FALSE;
    CTC_ERROR_GOTO(_sys_tmg_serdes_margin_set_param(lchip, serdes_id, &margin),
        ret, RELEASE_PTR_RETURN);

    sal_printf("Eye Diagram:\n\n");

    for(volt = 0; volt <= v_max; volt++)
    {
        for(phase = 0; phase < p_max; phase++)
        {
            sal_printf("%s",eye_lv[p_max * volt + phase]);
        }
        sal_printf("\n");
    }

    return CTC_E_NONE;


RELEASE_PTR_RETURN:
    mem_free(eye_lv);

    return CTC_E_NONE;


}

int32 _sys_tmg_serdes_set_rx_dfe_en(uint8 lchip, uint16 serdes_id, uint8 en)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = Hss32GRxPerLaneCfg_t;

    Hss32GRxPerLaneCfg_m perlane_cfg;

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxDfeBypass_f(lane_id, fld_id);

    value   = (en == TRUE) ? 0 : 1;

    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

    cmd   = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip, serdes_id, DMPS_RX, TRUE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_RX, 0));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_req(lchip, serdes_id, DMPS_RX, FALSE));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_rx_dfe(uint8 lchip, uint16 serdes_id, uint32* p_data)
{
    uint16 dfe_tap[21] = {0};

    CTC_PTR_VALID_CHECK(p_data);

    /*9 fixed taps*/
     CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_TAP1_ADPT_VAL), &dfe_tap[0]));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_TAP2_ADPT_VAL), (dfe_tap+1)));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_TAP3_ADPT_VAL), (dfe_tap+2)));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_TAP4_ADPT_VAL), (dfe_tap+3)));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_TAP5_ADPT_VAL), (dfe_tap+4)));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_TAP6_ADPT_VAL), (dfe_tap+5)));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_TAP7_ADPT_VAL), (dfe_tap+6)));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_TAP8_ADPT_VAL), (dfe_tap+7)));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_TAP9_ADPT_VAL), (dfe_tap+8)));
    
     ///*12 float taps*/
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_FTAP0_CORR_MAG), &dfe_tap[9]));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_FTAP1_CORR_MAG), &dfe_tap[10]));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_FTAP2_CORR_MAG), &dfe_tap[11]));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_FTAP3_CORR_MAG), &dfe_tap[12]));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_FTAP4_CORR_MAG), &dfe_tap[13]));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_FTAP5_CORR_MAG), &dfe_tap[14]));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_FTAP6_CORR_MAG), &dfe_tap[15]));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_FTAP7_CORR_MAG), &dfe_tap[16]));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_FTAP8_CORR_MAG), &dfe_tap[17]));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_FTAP9_CORR_MAG), &dfe_tap[18]));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_FTAP10_CORR_MAG), &dfe_tap[19]));
     //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_FTAP11_CORR_MAG), &dfe_tap[20]));

     
     SYS_USW_VALID_PTR_WRITE((p_data+0), (uint32)dfe_tap[0]);
    
    return CTC_E_NONE;
}


int32 _sys_tmg_serdes_get_rx_dfe_en(uint8 lchip, uint16 serdes_id, uint8* p_en)
{
    uint16 value    = 0;

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_DFE_BYPASS), &value));

    SYS_USW_VALID_PTR_WRITE(p_en, (uint8)value);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_rx_cdr_det_en(uint8 lchip, uint16 serdes_id, uint8 enable)
{
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_CDR_DETECTOR_EN), (uint16)enable));
    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_rx_cdr_det_en(uint8 lchip, uint16 serdes_id, uint8* p_enable)
{
    uint16 value = 0;

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_CDR_DETECTOR_EN), &value));

    SYS_USW_VALID_PTR_WRITE(p_enable, (uint8)value);    

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_rx_lane_speed(uint8 lchip, uint16 serdes_id, uint8* p_spd)
{
    uint8 field_idx = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint8  macro_id = 0;
    uint8  lane_id  = 0;
    uint8  txrx_speed = 0;

    Hss32GRxPerLaneCfg_m rx_cfg;

    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    macro_id = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id  = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    /*step 1 read table*/
    cmd     = DRV_IOR(Hss32GRxPerLaneCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id,0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_cfg));

    for(txrx_speed = TMG_SERDES_SPEED_1_25G; txrx_speed < TMG_SERDES_SPEED_TOTALCNT; txrx_speed++)
    {
        for(field_idx = 0; field_idx < Hss32GRxPerLane_TOTALCNT; field_idx++)
        {
            switch(field_idx)
            {
                 case Hss32GRxPerLane_cfgRxRefLoadValue:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxRefLoadValue_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxVcoLoadValue:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxVcoLoadValue_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxCdrPpmMax:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxCdrPpmMax_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxEqAttLevel:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqAttLevel_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxEqCtleBoost:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqCtleBoost_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxEqCtlePole:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqCtlePole_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxEqAfeRate:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqAfeRate_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxEqVgaGain:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqVgaGain_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxEqAfeConfig:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqAfeConfig_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxEqDfeTap1:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqDfeTap1_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxEqDfeTap2:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqDfeTap2_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxDeltaIq:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxDeltaIq_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxCdrVcoConfig:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxCdrVcoConfig_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxDccCtrlDiffRange:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxDccCtrlDiffRange_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxDccCtrlCmRange:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxDccCtrlCmRange_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxSigdetLfThrd:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxSigdetLfThrd_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxSigdetHfThrd:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxSigdetHfThrd_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxMisc:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxMisc_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxTermCtrl:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxTermCtrl_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxWidth:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxWidth_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxRate:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxRate_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxDfeBypass:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxDfeBypass_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxOffcanCont:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxOffcanCont_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxAdaptCont:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxAdaptCont_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxEqDfeFloatEn:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxEqDfeFloatEn_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxCdrSscEn:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxCdrSscEn_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxSigdetHfEn:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxSigdetHfEn_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxSigdetLfpsFilterEn:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxSigdetLfpsFilterEn_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxTermAcdc:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxTermAcdc_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxAdaptSel:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxAdaptSel_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxAdaptMode:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxAdaptMode_f(lane_id, fld_id);
                    break;
                 case Hss32GRxPerLane_cfgRxAdaptEn:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxAdaptEn_f(lane_id, fld_id);
                 case Hss32GRxPerLane_cfgRxTermEn:
                    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxTermEn_f(lane_id, fld_id);
                    break;
            }

            DRV_IOR_FIELD(lchip, Hss32GTxPerLaneCfg_t, fld_id, &value, &rx_cfg);

            SYS_CONDITION_CONTINUE(g_rx_cfg_by_serdes_speed[field_idx][txrx_speed] != value);

        }

        /*match all ropll cfg*/
        SYS_CONDITION_BREAK(Hss32GRxPerLane_TOTALCNT == field_idx);       
    }

    txrx_speed = _sys_tmg_serdes_get_dmps_speed(txrx_speed);
    SYS_USW_VALID_PTR_WRITE(p_spd, txrx_speed);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_tx_lane_speed(uint8 lchip, uint16 serdes_id, uint8* p_spd)
{
    uint8 field_idx = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint8  macro_id = 0;
    uint8  lane_id  = 0;
    uint8  txrx_speed = 0;

    Hss32GTxPerLaneCfg_m tx_cfg;

    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    macro_id = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id  = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    /*step 1 read table*/
    cmd     = DRV_IOR(Hss32GTxPerLaneCfg_t, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id,0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_cfg));

    for(txrx_speed = TMG_SERDES_SPEED_1_25G; txrx_speed < TMG_SERDES_SPEED_TOTALCNT; txrx_speed++)
    {
        for(field_idx = 0; field_idx < Hss32GTxPerLane_TOTALCNT; field_idx++)
        {
            switch(field_idx)
            {
                case Hss32GTxPerLane_cfgTxMisc:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxMisc_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxDccCtrlDiffRange:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxDccCtrlDiffRange_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxDccCtrlCmRange:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxDccCtrlCmRange_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxWidth:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxWidth_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRopllCpCtlIntg:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllCpCtlIntg_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRopllCpCtlProp:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllCpCtlProp_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRopllRcFilter:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllRcFilter_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRopllV2iMode:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllV2iMode_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRopllVcoLowFreq:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllVcoLowFreq_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRopllPostDiv:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllPostDiv_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRate:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRate_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxTermCtrl:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxTermCtrl_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxDlyCalEn:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxDlyCalEn_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxPllWordClkFreq:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxPllWordClkFreq_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxDualCntxEn:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxDualCntxEn_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRopllBypass:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllBypass_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRopllRefDiv:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllRefDiv_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRopllRefSel:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllRefSel_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRopllFbDiv:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllFbDiv_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRopllOutDiv:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllOutDiv_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxRopllWordClkDivSel:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxRopllWordClkDivSel_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxFastEdgeEn:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxFastEdgeEn_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxAlignWideXferEn:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxAlignWideXferEn_f(lane_id, fld_id);
                    break;
                 case Hss32GTxPerLane_cfgTxPllEn:
                    dmps_Hss32GTxPerLaneCfg_hssTxCfg_0_cfgTxPllEn_f(lane_id, fld_id);
                    break;
            }

            DRV_IOR_FIELD(lchip, Hss32GTxPerLaneCfg_t, fld_id, &value, &tx_cfg);

            SYS_CONDITION_CONTINUE(g_tx_cfg_by_serdes_speed[field_idx][txrx_speed] != value);

        }

        /*match all ropll cfg*/
        SYS_CONDITION_BREAK(Hss32GTxPerLane_TOTALCNT == field_idx);       
    }

    txrx_speed = _sys_tmg_serdes_get_dmps_speed(txrx_speed);
    SYS_USW_VALID_PTR_WRITE(p_spd, txrx_speed);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_lane_speed(uint8 lchip, uint16 serdes_id, uint8 dir, uint8* p_spd)
{
    if(DMPS_RX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_get_rx_lane_speed(lchip, serdes_id, p_spd));  
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_get_tx_lane_speed(lchip, serdes_id, p_spd));  
    }

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_rx_cdr_lock(uint8 lchip, uint16 serdes_id, uint32* lock)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = Hss32GRxMon_t;

    Hss32GRxMon_m rx_mon;

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_mon));

    dmps_Hss32GRxMon_hssRxMon_0_monRxCdrLock_f(lane_id, fld_id);

    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &rx_mon);

    SYS_USW_VALID_PTR_WRITE(lock, value);

    return CTC_E_NONE;

}

/*unreliable flag*/
int32 _sys_tmg_serdes_get_rx_ready(uint8 lchip, uint16 serdes_id, uint8* p_ready)
{
    /*TBD*/
#if 0
    uint32 ready    = 0;
    uint8  sigdet   = 0;
    uint32 cdr_lock = 0;

    CTC_ERROR_RETURN(_sys_tmg_serdes_get_signal_detect(lchip, serdes_id, NULL, &sigdet));
    CTC_ERROR_RETURN(_sys_tmg_serdes_get_rx_cdr_lock(lchip, serdes_id, &cdr_lock));

    ready = cdr_lock & sigdet;
#endif

    SYS_USW_VALID_PTR_WRITE(p_ready, 0);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_lane_msblsb(uint8 lchip, uint16 serdes_id, uint8 dir, uint8 swap)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = Hss32GMacroCfg_t;

    Hss32GMacroCfg_m macro_cfg;

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macro_cfg));

    if(DMPS_RX == dir)
    {
        dmps_Hss32GMacroCfg_cfgHssL0RxBitReverse_f(lane_id, fld_id);
    }
    else
    {
        dmps_Hss32GMacroCfg_cfgHssL0TxBitReverse_f(lane_id, fld_id);
    }

    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &macro_cfg, hss_id, 0);

    cmd   = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macro_cfg));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_lane_msblsb(uint8 lchip, uint16 serdes_id, uint8 dir, uint8* p_msb_lsb)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = Hss32GMacroCfg_t;

    Hss32GMacroCfg_m macro_cfg;

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macro_cfg));

    if(DMPS_RX == dir)
    {
        dmps_Hss32GMacroCfg_cfgHssL0RxBitReverse_f(lane_id, fld_id);
    }
    else
    {
        dmps_Hss32GMacroCfg_cfgHssL0TxBitReverse_f(lane_id, fld_id);
    }

    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &macro_cfg);

    SYS_USW_VALID_PTR_WRITE(p_msb_lsb, value);

    return CTC_E_NONE;
}

///TODO: SigdetHf need to be confirmed
int32 _sys_tmg_serdes_get_rx_sigdet(uint8 lchip, uint16 serdes_id, uint8* sigdet)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = Hss32GRxMon_t;
    uint8  sigdet_lf = 0;
    //uint8  sigdet_hf = 0;

    Hss32GRxMon_m rx_mon;

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_mon));

    dmps_Hss32GRxMon_hssRxMon_0_monRxSigdetLowFreq_f(lane_id, fld_id);
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &rx_mon);
    sigdet_lf = value;

    /*high freq sigdet is unreliable*/
    #if 0 
    dmps_Hss32GRxMon_hssRxMon_0_monRxSigdetHf_f(lane_id, fld_id);
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &rx_mon);
    sigdet_hf = value;
    #endif

    SYS_USW_VALID_PTR_WRITE(sigdet, sigdet_lf);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_force_sigdet(uint8 lchip, uint16 serdes_id, uint8 force)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = force;
    uint32 tbl_id   = Hss32GMacroCfg_t;

    Hss32GMacroCfg_m macro_cfg;

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macro_cfg));

    dmps_Hss32GMacroCfg_cfgHssL0ForceSigDet_f(lane_id, fld_id);

    DRV_IOW_FIELD(lchip, tbl_id, fld_id, &value, &macro_cfg);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macro_cfg));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_sigdet_thrd(uint8 lchip, uint16 serdes_id, uint8 thrd)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 tbl_id   = Hss32GRxPerLaneCfg_t;
    uint32 value    = thrd;

    Hss32GRxPerLaneCfg_m perlane_cfg;

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxSigdetLfThrd_f(lane_id, fld_id);

    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxSigdetHfThrd_f(lane_id, fld_id);

    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &perlane_cfg, hss_id, 0);

    cmd   = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_rx_sigdet_lf_thrd(uint8 lchip, uint16 serdes_id, uint32* value)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 tbl_id   = Hss32GRxPerLaneCfg_t;

    Hss32GRxPerLaneCfg_m perlane_cfg;

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &perlane_cfg));

    dmps_Hss32GRxPerLaneCfg_hssRxCfg_0_cfgRxSigdetLfThrd_f(lane_id, fld_id);

    DRV_IOR_FIELD(lchip, tbl_id, fld_id, value, &perlane_cfg);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_ctle_en(uint8 lchip, uint16 serdes_id, uint16 value)
{
    //CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, ));
    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_ctle_en(uint8 lchip, uint16 serdes_id, uint16 value)
{
    //CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, ));
    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_force_ready(uint8 lchip, uint16 serdes_id, uint8* is_fc, uint8* fc_val)
{
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint32 tbl_id   = Hss32GMacroCfg_t;

    Hss32GMacroCfg_m macro_cfg;

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macro_cfg));

    dmps_Hss32GMacroCfg_cfgHssL0ForceSigDet_f(lane_id, fld_id);

    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &macro_cfg);

    SYS_USW_VALID_PTR_WRITE(is_fc, (uint8)value);
    SYS_USW_VALID_PTR_WRITE(fc_val, 1);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_signal_detect(uint8 lchip, uint16 serdes_id, uint8* p_is_detect, uint8* p_raw_sigdet)
{
    uint8 sigdet = 0;
    uint8 is_fc  = 0;
    uint8 fc_val = 0;

    CTC_ERROR_RETURN(_sys_tmg_serdes_get_rx_sigdet(lchip, serdes_id, &sigdet));

    CTC_ERROR_RETURN(_sys_tmg_serdes_get_force_ready(lchip, serdes_id, &is_fc, &fc_val));

    SYS_USW_VALID_PTR_WRITE(p_raw_sigdet, sigdet);
    SYS_USW_VALID_PTR_WRITE(p_is_detect, (uint8)(is_fc ? fc_val : sigdet));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_lane_port_info(uint8 lchip, uint16 serdes_id, void* p_data)
{
    uint16 psd_s = 0;
    uint16 psd_d[DMPS_MAX_NUM_PER_MODULE] = {0};
    uint8  psd_num = 0;
    uint16 lport = 0;
    uint16 drv_port = 0;
    uint8  gchip = 0;
    uint8  ocs = 0;
    uint8  rx_ready = 0;
    ctc_port_serdes_info_t* p_serdes_port = (ctc_port_serdes_info_t*)p_data;

    CTC_PTR_VALID_CHECK(p_serdes_port);
    psd_s = serdes_id;

    CTC_ERROR_RETURN(sys_usw_dmps_db_get_relative_id(lchip, DMPS_DB_TYPE_PSD, psd_s,
        DMPS_DB_TYPE_PSD, &psd_num, psd_d));
    SYS_CONDITION_RETURN(psd_num > CTC_PORT_SERDES_MAX_NUM, CTC_E_INVALID_PARAM);
    p_serdes_port->serdes_num = psd_num;
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_lport_by_psd(lchip, psd_s, &lport));
    drv_port                          = lport;
    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));
    p_serdes_port->gport              = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, drv_port);
    sal_memcpy(p_serdes_port->serdes_id_array, psd_d, psd_num * sizeof(uint16));
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_ifmode(lchip, lport, &(p_serdes_port->serdes_mode)));
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_serdes_ocs(lchip, lport, &ocs));
    p_serdes_port->overclocking_speed = ocs;

    CTC_ERROR_RETURN(_sys_tmg_serdes_get_signal_detect(lchip, psd_s, NULL, &(p_serdes_port->signal_detect)));
    CTC_ERROR_RETURN(_sys_tmg_serdes_get_rx_ready(lchip, psd_s, &rx_ready));
    p_serdes_port->ready = rx_ready;

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_lane_swap(uint8 lchip, void* p_data)
{
uint16  dport_list[SYS_TMG_LANE_NUM_PER_HSS] = {0};
    uint8   dport_num     = 0;
    uint16  dport       = 0;
    uint16  chan_id     = 0;
    uint16  serdes_end  = 0;
    uint16* p_map       = NULL;
    uint16  lsd_lane    = 0;
    uint16  psd_lane    = 0;
    uint16  lsd         = 0;
    uint16  psd         = 0;
    uint16  psd0        = 0;
    uint16  mac_id      = 0;
    uint16  pcs_id      = 0;
    uint16  hss_id      = 0;
    uint16  serdes_base = 0;
    uint16  psd0_flag   = 0;
    uint16  psd_flag    = 0;
    uint8   swap02_flag = 0;
    uint8   cur_swap_flag = 0;
    uint8   dp_id       = 0;
    uint8   occupy_flag = 0;
    uint32  support_speed =0;
    
    ctc_chip_serdes_info_t serdes_info = {0};
    sys_dmps_db_upt_info_t port_info   = {0};

    CTC_PTR_VALID_CHECK(p_data);
    p_map = (uint16*) ((ctc_chip_serdes_map_cfg_t*)p_data)->serdes_id;

    /*. should assign 02 swap or not*/                     
    if(DMPS_INVALID_VALUE_U16 == p_map[0] && DMPS_INVALID_VALUE_U16 == p_map[2])
    {
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% Should assign 02 swap or not!\n");
        return CTC_E_INVALID_PARAM;
    }
    /*. check if in hss group */
    for(lsd_lane = 0; lsd_lane < SYS_TMG_LANE_NUM_PER_HSS; lsd_lane++)
    {
        SYS_CONDITION_BREAK(DMPS_INVALID_VALUE_U16 != p_map[lsd_lane]);
    }

    hss_id = SYS_TMG_GET_HSS_ID_BY_SERDES(p_map[lsd_lane]);
    for(lsd_lane = 0; lsd_lane < SYS_TMG_LANE_NUM_PER_HSS; lsd_lane++)
    {
        SYS_CONDITION_CONTINUE(DMPS_INVALID_VALUE_U16 == p_map[lsd_lane]);
        SYS_CONDITION_RETURN(hss_id != SYS_TMG_GET_HSS_ID_BY_SERDES(p_map[lsd_lane]), CTC_E_INVALID_PARAM);
    }
    serdes_base = hss_id * SYS_TMG_LANE_NUM_PER_HSS;
    serdes_end  = serdes_base + SYS_TMG_LANE_NUM_PER_HSS;
    
    /*. check if serdes duplicate */
    for(lsd_lane = 0; lsd_lane < SYS_TMG_LANE_NUM_PER_HSS; lsd_lane++)
    {
        SYS_CONDITION_CONTINUE(p_map[lsd_lane] == DMPS_INVALID_VALUE_U16);
    
        psd_lane = p_map[lsd_lane] - serdes_base;
        if(psd_flag & (1 << psd_lane))
        {
            SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% Physical Serdes Duplicated!\n");
            return CTC_E_INVALID_PARAM;
        }
        else
        {
            psd_flag |= (1 << psd_lane);
        }
    }

    /* check wether psd is the same */
    for(lsd_lane = 0; lsd_lane < SYS_TMG_LANE_NUM_PER_HSS; lsd_lane++)
    {
        lsd = serdes_base + lsd_lane;
        (void) sys_usw_dmps_db_get_relative_id(lchip, DMPS_DB_TYPE_LSD, lsd, DMPS_DB_TYPE_PSD, NULL, &psd0);
        if (DMPS_INVALID_VALUE_U16 != psd0)
        {
            psd0_flag |= 1 << (psd0 % SYS_TMG_LANE_NUM_PER_HSS);
        }
    }
    
    if (psd_flag != psd0_flag)
    {
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% Cannot change serdes when do lane swap!\n");
        return CTC_E_INVALID_PARAM;
    }

    /*. lane1 and lane3 not support swap*/
    SYS_CONDITION_RETURN(DMPS_INVALID_VALUE_U16 != p_map[1] &&
                         serdes_base + 1 != p_map[1] , CTC_E_INVALID_PARAM);
    SYS_CONDITION_RETURN(DMPS_INVALID_VALUE_U16 != p_map[3] &&
                         serdes_base + 3 != p_map[3] , CTC_E_INVALID_PARAM);

    swap02_flag = (p_map[0] != DMPS_INVALID_VALUE_U16) ? p_map[0] != serdes_base : p_map[2] == serdes_base;

    /*. get current swap status*/
    for(lsd_lane = 0; lsd_lane < SYS_TMG_LANE_NUM_PER_HSS; lsd_lane++)
    {
        SYS_CONDITION_CONTINUE(lsd_lane != 0 && lsd_lane != 2);
        lsd = serdes_base + lsd_lane;
        (void) sys_usw_dmps_db_get_relative_id(lchip, DMPS_DB_TYPE_LSD, lsd, DMPS_DB_TYPE_PSD, NULL, &psd0);
        if (DMPS_INVALID_VALUE_U16 != psd0)
        {
            cur_swap_flag = !(lsd == psd0);
            break;    
        }
    }

    SYS_CONDITION_RETURN(cur_swap_flag == swap02_flag, CTC_E_NONE);
 
    /*. switch logic serdes to none mode */
    for(lsd_lane = 0; lsd_lane < SYS_TMG_LANE_NUM_PER_HSS; lsd_lane++)
    {
        SYS_CONDITION_CONTINUE(lsd_lane != 0 && lsd_lane != 2);
        lsd = serdes_base + lsd_lane;
        (void) sys_usw_dmps_db_get_relative_id(lchip, DMPS_DB_TYPE_LSD, lsd, DMPS_DB_TYPE_PSD, NULL, &psd0);
        if (DMPS_INVALID_VALUE_U16 != psd0)
        {
            serdes_info.serdes_mode        = CTC_CHIP_SERDES_NONE_MODE;
            serdes_info.overclocking_speed = CTC_CHIP_SERDES_OCS_MODE_NONE;
            serdes_info.serdes_id = psd0;
            CTC_ERROR_RETURN(_sys_usw_port_api_set_serdes_mode(lchip, &serdes_info));
        }
    }

    /* reconfig psd & lsd mapping*/
    for (lsd = serdes_base; lsd < serdes_end; lsd++)
    {
        lsd_lane = SYS_TMG_GET_INNER_LANE_BY_SERDES(lsd);    
        SYS_CONDITION_CONTINUE(lsd_lane != 0 && lsd_lane != 2);
        
        if (sys_usw_dmps_db_is_valid_id(lchip, DMPS_DB_TYPE_LSD, lsd))
        {
            CTC_ERROR_RETURN(_sys_tmg_datapath_get_lport_chan_by_serdes(lchip, lsd, &chan_id, &dport));
            if ((DMPS_INVALID_VALUE_U16 == chan_id) || (DMPS_INVALID_VALUE_U16 == dport))
            {
                return CTC_E_INVALID_PARAM;
            }
            dport_list[dport_num] = dport;
            dport_num++;
            CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_DPORT,            dport);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_CHAN_ID,          chan_id);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_CHAN_RX_ID,       chan_id);
            DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_PORT_IS_RSV, FALSE);
            DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_IS_RSV, FALSE);
            DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_RX_IS_RSV, FALSE);
            CTC_ERROR_RETURN(sys_usw_dmps_db_set_port_info(lchip, &port_info));
            CTC_ERROR_RETURN(sys_usw_dmps_db_free_chan(lchip, chan_id));
            CTC_ERROR_RETURN(sys_usw_dmps_db_free_port(lchip, dport));
            CTC_ERROR_RETURN(sys_usw_dmps_db_set_chan2lsd(lchip, 0, chan_id, 
                SYS_DP_CHAN_LPORT_OCCUPY_RSV, DMPS_INVALID_VALUE_U16, DMPS_INVALID_VALUE_U16));

            CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_LOGIC_SERDES,      lsd);
            CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &port_info));
            DMPS_DB_SET_MAP_UPDATE(port_info);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_OLD_DPORT,         port_info.dport);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_OLD_CHAN_ID,       port_info.chan_id);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_OLD_CHAN_RX_ID,    port_info.chan_rx_id);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_OLD_MAC_ID,        port_info.mac_id);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_OLD_PCS_ID,        port_info.pcs_id);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_OLD_LOGIC_SERDES,  port_info.logic_serdes);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_OLD_PHYSIC_SERDES, port_info.physic_serdes);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_DPORT,             DMPS_INVALID_VALUE_U16);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_CHAN_ID,           DMPS_INVALID_VALUE_U16);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_CHAN_RX_ID,        DMPS_INVALID_VALUE_U16);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_MAC_ID,            DMPS_INVALID_VALUE_U16);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_PCS_ID,            DMPS_INVALID_VALUE_U16);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_LOGIC_SERDES,      DMPS_INVALID_VALUE_U16);
            DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_PHYSIC_SERDES,     DMPS_INVALID_VALUE_U16);
            CTC_ERROR_RETURN(sys_usw_dmps_db_set_port_info(lchip, &port_info));
        }
    }

    /* 3.2 Add new map and property */
    dport_num = 0;
    for (lsd = serdes_base; lsd < serdes_end; lsd++)
    {
        lsd_lane = SYS_TMG_GET_INNER_LANE_BY_SERDES(lsd);    
        SYS_CONDITION_CONTINUE(lsd_lane != 0 && lsd_lane != 2);
    
        if (DMPS_INVALID_VALUE_U16 == p_map[lsd % SYS_TMG_LANE_NUM_PER_HSS])
        {
            continue;
        }

        dp_id = lsd / SYS_TMG_MAX_SERDES_NUM_PER_DP;

        for(chan_id = dp_id * SYS_TMG_CHANNEL_NUM_PER_DP; chan_id < (dp_id + 1) * SYS_TMG_CHANNEL_NUM_PER_DP; chan_id++)
        {
            CTC_ERROR_RETURN(sys_usw_dmps_db_get_chan2lsd(lchip, 0, chan_id, &occupy_flag, NULL, NULL));
            if(SYS_DP_CHAN_LPORT_OCCUPY_RSV == occupy_flag)
            {
                break;
            }
        }

        dport    = dport_list[dport_num];
        dport_num++;
        CTC_ERROR_RETURN(sys_usw_dmps_db_set_chan2lsd(lchip, 0, chan_id, SYS_DP_CHAN_LPORT_OCCUPY_IN_USE, lsd, dport));
        /* opf: Assign channel and port */
        CTC_ERROR_RETURN(sys_usw_dmps_db_assign_chan(lchip, chan_id));
        CTC_ERROR_RETURN(sys_usw_dmps_db_assign_port(lchip, dport));

        /* set dport and chan property */
        CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
        DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_DPORT,                   dport);
        DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_CHAN_ID,                 chan_id);
        DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_CHAN_RX_ID,              chan_id);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_PORT_IS_RSV,        TRUE);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_IS_RSV,        TRUE);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_DP_ID,         g_dmps_map_tmg[lsd].dp_id);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_TXQM_ID,       g_dmps_map_tmg[lsd].txqm_id);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_MAC_CLIENT_ID, g_dmps_map_tmg[lsd].mac_client % SYS_TMG_MAC_CLIENT_NW_NUM_PER_DP);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_SUB_CHAN_ID,   SYS_TMG_CHANNEL_TO_DPCHAN(chan_id));
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_PRIO,          FALSE);

        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_RX_IS_RSV,        TRUE);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_RX_DP_ID,         g_dmps_map_tmg[lsd].dp_id);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_RX_TXQM_ID,       g_dmps_map_tmg[lsd].txqm_id);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_RX_MAC_CLIENT_ID, g_dmps_map_tmg[lsd].mac_client % SYS_TMG_MAC_CLIENT_NW_NUM_PER_DP);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_RX_SUB_CHAN_ID,   SYS_TMG_CHANNEL_TO_DPCHAN(chan_id));
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_RX_PRIO,          FALSE);

        CTC_ERROR_RETURN(sys_usw_dmps_db_set_port_info(lchip, &port_info));

        /* set mac, pcs, lsd and psd property */
        psd    = p_map[lsd % SYS_TMG_LANE_NUM_PER_HSS];
        mac_id = lsd;
        pcs_id = lsd;
        support_speed  = _sys_tmg_datapath_get_serdes_support_speed_bmp(lchip, lsd);
        CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
        DMPS_DB_SET_MAP_UPDATE(port_info);
        DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_MAC_ID,        mac_id);
        DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_PCS_ID,        pcs_id);
        DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_LOGIC_SERDES,  lsd);
        DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_PHYSIC_SERDES, psd);
        /* MAC DB */
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_MAC_EN,       FALSE);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_MAC_SPEED,    0);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_MAC_GROUP_ID, SYS_TMG_GET_MAC_GROUP(mac_id));
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_MAC_IDX,      SYS_TMG_GET_QUAD_MAC_ID(mac_id));
        /* PCS DB */
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_PCS_IDX, SYS_TMG_GET_QUAD_MAC_ID(mac_id));
        /* LSD DB */
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_LSD_LANE_ID,  lsd % SYS_TMG_LANE_NUM_PER_HSS);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_LSD_PCSL_IDX, 0);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_LSD_HSS_ID,   SYS_TMG_GET_HSS_ID_BY_SERDES(lsd));
        /* PSD DB */
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_PSD_PLL_SEL,       0);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_PSD_RATE_DIV,      0);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_PSD_BIT_WIDTH,     0);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_PSD_OCS,           CTC_CHIP_SERDES_OCS_MODE_NONE);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_PSD_LANE_ID,       psd % SYS_TMG_LANE_NUM_PER_HSS);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_PSD_SUPPORT_SPEED, support_speed);
        DMPS_DB_SET_PROPERTY_INFO(port_info, DMPS_DB_PSD_SPEED,         0);
        CTC_ERROR_RETURN(sys_usw_dmps_db_set_port_info(lchip, &port_info));
    }
    
    /*. cfg hw table*/
    CTC_ERROR_RETURN(sys_tmg_datapath_lane_swap_cfg(lchip, hss_id, swap02_flag));   

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_training_en(uint8 lchip, uint16 serdes_id, uint16 enable)
{
    /*TBD*/

    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_ENABLE), enable));

    return CTC_E_NONE;
}
int32 _sys_tmg_serdes_get_training_en(uint8 lchip, uint16 serdes_id, uint16* p_enable)
{
    /*TBD*/

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_ENABLE), p_enable));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_tx_train_stat(uint8 lchip, uint16 serdes_id, uint8* p_en, uint8* p_stat, uint32* p_reason)
{
    /*TBD*/
    uint8  hss_id   = 0;
    uint8  lane_id  = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint16 val_16   = 0;
    uint16 lt_en    = 0;
    uint32 tbl_id   = Hss32GLtMon_t;
    sys_tmg_lt_status_t lt_status = {0};

    Hss32GLtMon_m lt_mon;

    hss_id  = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_ENABLE), &lt_en));
    SYS_USW_VALID_PTR_WRITE(p_en, (uint8)lt_en);

    index = DRV_INS(hss_id, 0);
    cmd   = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &lt_mon));

    dmps_Hss32GLtMon_hssLtMon_0_monLtStart_f(lane_id, fld_id);
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &lt_mon);
    lt_status.lt_start = value;

    dmps_Hss32GLtMon_hssLtMon_0_monLtComplete_f(lane_id, fld_id);
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &lt_mon);
    lt_status.lt_complete = value;

    dmps_Hss32GLtMon_hssLtMon_0_monLtDone_f(lane_id, fld_id);
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &lt_mon);
    lt_status.lt_done = value;

    dmps_Hss32GLtMon_hssLtMon_0_monLtFail_f(lane_id, fld_id);
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &lt_mon);
    lt_status.lt_fail = value;

    dmps_Hss32GLtMon_hssLtMon_0_monLtFrameLock_f(lane_id, fld_id);
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &lt_mon);
    lt_status.lt_framelock = value;

    dmps_Hss32GLtMon_hssLtMon_0_monLtInProgress_f(lane_id, fld_id);
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &value, &lt_mon);
    lt_status.lt_progress = value;

    if(TRUE == lt_en)
    {
        if(lt_status.lt_progress)
        {
            SYS_USW_VALID_PTR_WRITE(p_stat, SYS_PORT_CL72_PROGRESS);
        }
        else if(lt_status.lt_fail)
        {
            SYS_USW_VALID_PTR_WRITE(p_stat, SYS_PORT_CL72_FAIL);
        }
        else if(lt_status.lt_done)
        {
            SYS_USW_VALID_PTR_WRITE(p_stat, SYS_PORT_CL72_OK);
        }
    }
    else
    {
        SYS_USW_VALID_PTR_WRITE(p_stat, SYS_PORT_CL72_DISABLE);
    }

    if(lt_status.lt_fail)
    {
        /*if not restart lt, FSM will stay at TRAIN_FAIL STATE, state_his[3:0] is latest history state*/    
        CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_CTRL_FSM_STATE_HIS), &val_16));
        val_16 = val_16 & 0xF;

        if(TMG_LT_FSM_SEND_TR == val_16)
        {
            SYS_USW_VALID_PTR_WRITE(p_reason, 1);
        }
        else if(TMG_LT_FSM_TRAIN_LOCAL == val_16)
        {
            SYS_USW_VALID_PTR_WRITE(p_reason, 2);
        }       
        else if(TMG_LT_FSM_TRAIN_REMOTE == val_16)
        {
            SYS_USW_VALID_PTR_WRITE(p_reason, 3);
        }
    }
    else
    {
        SYS_USW_VALID_PTR_WRITE(p_reason, 0);
    }
    

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_anlt_pre_config(uint8 lchip, uint16 serdes_id)
{
    /*TBD*/
    sys_dmps_db_upt_info_t port_info;
    uint16 serdes_mode;
    uint8  pcs_type_sel = 0;

    uint16 val_16;
    uint16 lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    /*disable an ok trigger lt start*/
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_START_EN_AFTR_AN), 0));
    /*enable anlt interrupt*/
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_ANLT_TOP_LT_INT_ENABLE), &val_16));
    CTC_BIT_SET(val_16, lane_id);
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_ANLT_TOP_LT_INT_ENABLE),val_16));
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_INT_ENABLE_LT_TRAIN_OVER),1));

    CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
    DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PORT_IF_MODE);
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &port_info));
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PORT_IF_MODE, serdes_mode);
    pcs_type_sel = _sys_tmg_serdes_map_serdes_mode_to_pcs_type_sel(serdes_mode);
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_AN_MODE_CTRL_PCS_TYPE_SEL), pcs_type_sel));

    /*Guarantee rxX_adapt_in_prog asserted before lt_phyrx_reset in link-training*/
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RXADAPT_IN_PROG_TIME), 0x40));

/*for fast sim, reduce timer cfg*/
#ifdef TMG_SERDES_SIM
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_AN_WAIT_TIMER),0xf44));
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_AN_BREAK_TIMER),0x1));
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_LINKRDY_WAIT_TIME),0x1000));
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_MAX_WAIT_TIMEH),0x0));
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_MAX_WAIT_TIMEL),0xffff));
#endif
    
    return CTC_E_NONE;       
}

int32 sys_tmg_serdes_trigger_prbs_error(uint8 lchip, uint16 serdes_id)
{
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_PRBS_TRIGGER_ERR), 1));
    return CTC_E_NONE;
}

int32 sys_tmg_serdes_get_serdes_auto_neg_local_ability(uint8 lchip, uint16 serdes_id, sys_datapath_an_ability_t* p_ability)
{

    uint16  value_arr[3] = {0};

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_ADV1), &value_arr[0]));
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_ADV2), &value_arr[1]));
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_ADV3), &value_arr[2]));

    p_ability->base_ability0 = value_arr[1] << 16 | value_arr[0];
    p_ability->base_ability1 = value_arr[2];

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_UF_XNP_TX1), &value_arr[0]));
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_UF_XNP_TX2), &value_arr[1]));
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_UF_XNP_TX3), &value_arr[2]));

    p_ability->np1_ability0 = value_arr[1] << 16 | value_arr[0];
    p_ability->np1_ability1 = value_arr[2];

    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n", __FUNCTION__,"serdes_id",     serdes_id);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n",__FUNCTION__, "base_ability0", p_ability->base_ability0);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n", __FUNCTION__,"base_ability1", p_ability->base_ability1);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n", __FUNCTION__,"np0_ability0",  p_ability->np0_ability0);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n", __FUNCTION__,"np0_ability1",  p_ability->np0_ability1);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n", __FUNCTION__,"np1_ability0",  p_ability->np1_ability0);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n", __FUNCTION__,"np1_ability1",  p_ability->np1_ability1);

    return CTC_E_NONE;
}

int32 sys_tmg_serdes_get_serdes_auto_neg_remote_ability(uint8 lchip, uint16 serdes_id, sys_datapath_an_ability_t* p_ability)
{
    uint16  value_arr[3] = {0};

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LP_AN_ABL1), &value_arr[0]));
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LP_AN_ABL2), &value_arr[1]));
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LP_AN_ABL3), &value_arr[2]));

    p_ability->base_ability0 = value_arr[1] << 16 | value_arr[0];
    p_ability->base_ability1 = value_arr[2];

    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_LP_UF_XNP_ABL1), &value_arr[0]));
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_LP_UF_XNP_ABL2), &value_arr[1]));
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_LP_UF_XNP_ABL3), &value_arr[2]));

    p_ability->np1_ability0 = value_arr[1] << 16 | value_arr[0];
    p_ability->np1_ability1 = value_arr[2];

    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n", __FUNCTION__,"serdes_id",     serdes_id);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n",__FUNCTION__, "base_ability0", p_ability->base_ability0);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n", __FUNCTION__,"base_ability1", p_ability->base_ability1);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n", __FUNCTION__,"np0_ability0",  p_ability->np0_ability0);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n", __FUNCTION__,"np0_ability1",  p_ability->np0_ability1);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n", __FUNCTION__,"np1_ability0",  p_ability->np1_ability0);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [%s] %-32s : 0x%08x\n", __FUNCTION__,"np1_ability1",  p_ability->np1_ability1);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_serdes_auto_neg_ability(uint8 lchip, uint16 serdes_id)
{
    uint16  value_arr[3]    = {0};
    uint32  base_ability0   = 0;
    uint32  base_ability1   = 0;
    uint32  np1_ability0    = 0;
    uint32  np1_ability1    = 0;
    sys_dmps_db_upt_info_t  port_info = {0};

    DP_DEBUG_FUNCTION_CALLED_PRINT();


    CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
    DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PORT_BP_ABILITY0);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PORT_BP_ABILITY1);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PORT_NP1_ABILITY0);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PORT_NP1_ABILITY1);
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &port_info));
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PORT_BP_ABILITY0 , base_ability0);
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PORT_BP_ABILITY1 , base_ability1);
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PORT_NP1_ABILITY0, np1_ability0);
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PORT_NP1_ABILITY1, np1_ability1);

    sal_fprintf(g_tm_dump_fp,"//serdes:%u, bp ability0:0x%X, bp ability1:0x%X, np1 ability0:0x%X, np1 ability1:0x%X\n", serdes_id,
                    base_ability0, base_ability1, np1_ability0, np1_ability1);

    /*base page*/
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_ADV1), &value_arr[0]));
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_ADV2), &value_arr[1]));
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_ADV3), &value_arr[2]));

    value_arr[0] &= 0x7FFF;
    value_arr[0] |= (uint16) (base_ability0 & 0x0000FFFF);
    value_arr[1] &= 0x001F;
    value_arr[1] |= (uint16) (base_ability0 >> 16);
    value_arr[2] &= 0x0FE0;
    value_arr[2] |= (uint16) (base_ability1 & 0x0000FFFF);

    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_ADV1), value_arr[0]));
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_ADV2), value_arr[1]));
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_ADV3), value_arr[2]));

    if(np1_ability0 || np1_ability1)
    {
        /* NP0 message page*/

        value_arr[0] = 0xA005;
        value_arr[1] = 0x0353;
        value_arr[2] = 0x04DF;

        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_XNP_TX1), value_arr[0]));
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_XNP_TX2), value_arr[1]));
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_XNP_TX3), value_arr[2]));

        /* NP1 unformatted next page*/

        CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_UF_XNP_TX1), &value_arr[0]));
        CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_UF_XNP_TX2), &value_arr[1]));
        CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_UF_XNP_TX3), &value_arr[2]));

        value_arr[0] = 0x0203;
        value_arr[1] &= 0xFCCF;
        value_arr[1] |= (uint16) (np1_ability0 >> 16);
        value_arr[2] &= 0xE01B;
        value_arr[2] |= (uint16) (np1_ability1 & 0x0000FFFF);

        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_UF_XNP_TX1), value_arr[0]));
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_UF_XNP_TX2), value_arr[1]));
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_VR_UF_XNP_TX3), value_arr[2]));

        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_AUTO_NP_EN), TRUE));
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SREDES_AN_CTRL_EXT_NP_CTL), TRUE));

    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_AUTO_NP_EN), FALSE));
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SREDES_AN_CTRL_EXT_NP_CTL), FALSE));
    }

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

/// TODO
int32 _sys_tmg_serdes_set_serdes_auto_neg_en(uint8 lchip, uint16 serdes_id, uint16 enable)
{

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    if(enable)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_ability(lchip, serdes_id));
        /*due to lower line speed and high ref speed, close cdr detector*/
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_CDR_DETECTOR_EN), 0));
    }

    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_ENABLE), enable));

    if(enable)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_RESTART), 1));
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_RESTART), 0));
    }
    else
    {
        /*recover cdr detector enable in force mode*/
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_CDR_DETECTOR_EN), 1));
    }

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

uint8 _sys_tmg_serdes_map_serdes_mode_to_pcs_type_sel(uint16 serdes_mode)
{
    uint32 ret_value = 0;
    switch(serdes_mode)
    {
        case CTC_CHIP_SERDES_SGMII_MODE:
            ret_value = 0;
            break;
        case CTC_CHIP_SERDES_2DOT5G_MODE:
            ret_value = 1;
            break;
        case CTC_CHIP_SERDES_XFI_MODE:
            ret_value = 4;
            break;
        case CTC_CHIP_SERDES_XXVG_MODE:
            ret_value = 5;
            break;
        case CTC_CHIP_SERDES_XLG_MODE:
            ret_value = 6;
            break;
        case CTC_CHIP_SERDES_LG_MODE:
            ret_value = 7;
            break;
        case CTC_CHIP_SERDES_CG_MODE:
            ret_value = 8;
            break;
        default:
            break;
    }

    return ret_value;
}

int32 _sys_tmg_serdes_set_tx_train_en(uint8 lchip, uint16 serdes_id, uint8 enable)
{
#ifdef TMG_SERDES_SIM    
    uint16 serdes_mode;
    sys_dmps_db_upt_info_t port_info;
#endif
    uint32 lt_train_on = 0;
    uint32 tbl_id      = 0;
    uint32 fld_id      = 0;
    uint32 index       = 0;
    uint8  lane_id     = 0;
    uint8  macro_id    = 0;
    uint32 cmd         = 0;

    Hss32GLtMon_m lt_mon;
    
    DP_DEBUG_FUNCTION_CALLED_PRINT();

    if(enable)
    {
        /*for fast sim, reduce timer cfg*/
#ifdef TMG_SERDES_SIM

        CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
        DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_TYPE_PSD, serdes_id);
        DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PORT_IF_MODE);
        CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &port_info));
        DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PORT_IF_MODE, serdes_mode);

        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_LINKRDY_WAIT_TIME),0x1000));

        /*10G : CL72   25G : CL92 */
        if(serdes_mode == CTC_CHIP_SERDES_XFI_MODE || serdes_mode == CTC_CHIP_SERDES_XLG_MODE)
        {
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_CL72_SEL), TRUE));
            /*
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_MAX_WAIT_TIMEL), 0xB1C8));
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_MAX_WAIT_TIMEH), 0x99A));
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_LINKRDY_WAIT_TIME), 0x6B08));
            */
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RX_TRAIN_TIME_L), 0x3778));
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RX_TRAIN_TIME_H), 0x5C3));
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RX_EQ_SEQ_PAR_SEL), 0));
        }
        else if(serdes_mode == CTC_CHIP_SERDES_XXVG_MODE || serdes_mode == CTC_CHIP_SERDES_LG_MODE || serdes_mode == CTC_CHIP_SERDES_CG_MODE)
        {
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_CL72_SEL), FALSE));
            /*
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_MAX_WAIT_TIMEL), 0xBA80));
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_MAX_WAIT_TIMEH), 0x1802));
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_LINKRDY_WAIT_TIME), 0xD610));
            */
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RX_TRAIN_TIME_L), 0x980));
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RX_TRAIN_TIME_H), 0xE68));
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RX_EQ_SEQ_PAR_SEL), 0));
        }
        
#endif
    }


    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_ENABLE), (uint16)enable));

    if(enable)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RESTART), TRUE));
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RESTART), FALSE));
    }

    
    /*if link training is interrupted when it is processing , rx adapt will stuck at waiting state*/ 
    /*recover step*/
    /*  
        1.toggle LT soft reset , keep assert in sim at least wait for 200ns 
        2.toggle rxX_reset , need keep assert for at least 10 ref clock
        3.wait for rxX_ack set to 0 
        4.restart LT
    */

    lane_id     = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);
    macro_id    = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);

    tbl_id = Hss32GLtMon_t;
    dmps_Hss32GLtMon_hssLtMon_0_monLtInProgress_f(lane_id, fld_id);
    index  = DRV_INS(macro_id, 0);
    cmd    = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);

    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &lt_mon));

    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &lt_train_on, &lt_mon);

    if(lt_train_on)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_anlt_reset(lchip, serdes_id, DMPS_RX, 1));
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
        sal_task_sleep(1);
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_anlt_reset(lchip, serdes_id, DMPS_RX, 0));
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, DMPS_RX, 1)); 
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
        sal_task_sleep(1);
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, DMPS_RX, 0)); 
        CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_RX, 0)); 
    }

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_set_lane_en(uint8 lchip, uint16 serdes_id, uint8 dir, uint8 en)
{
    uint16 value = en;

    if(CTC_EGRESS == dir)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_TX_DATA_EN_LOW), value));
    }
    else
    {
        /*rx data enable relys on sigdet low freq*/
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%s, %d\n", __FUNCTION__, __LINE__);
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_lane_en(uint8 lchip, uint16 serdes_id, uint8 dir, uint8* p_en)
{
    uint16 val_16    = 0;

    CTC_PTR_VALID_CHECK(p_en);

    if(CTC_EGRESS == dir)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_TX_DATA_EN_LOW), &val_16));
        *p_en = val_16;
    }
    else
    {
        *p_en = TRUE;
    }

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_lane_pll_lock(uint8 lchip, uint16 serdes_id, uint8 dir, uint8* lock)
{
    uint16 value = 0;

    /*tx ropll locks*/
    if(DMPS_TX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_ROPLL_PH_LOCK), &value));
    }
    else
    {
        /*TOD*/
    }

    SYS_USW_VALID_PTR_WRITE(lock, (uint8)value);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_group_pll_lock(uint8 lchip, uint16 serdes_id, uint8* p_pll_lock)
{
    uint16 value = 0;

    CTC_PTR_VALID_CHECK(p_pll_lock);
    
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_MPLLA_CONT_LOCK_DET_EN), 1));
    CTC_ERROR_RETURN(_sys_tmg_serdes_read_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_MPLLA_VCO_DRIFT), &value));

    *p_pll_lock = (TRUE == value) ? FALSE : TRUE;

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_mask_sigdet(uint8 lchip, uint16 serdes_id, uint32 mask)
{
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint32 value    = 0;
    uint8  macro_id   = 0;
    uint8  lane_id  = 0;

    Hss32GMacroCfg_m macro_cfg;

    macro_id = SYS_TMG_GET_MAC_GROUP(serdes_id);
    lane_id  = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);

    tbl_id  = Hss32GMacroCfg_t;
    dmps_Hss32GMacroCfg_cfgHssL0RxSigDetMask_f(lane_id, fld_id);

    cmd     = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macro_cfg));

    value = mask;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &macro_cfg, macro_id, 0);

    cmd     = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macro_cfg));

    return CTC_E_NONE;
}


int32 _sys_tmg_serdes_pre_config_per_lane(uint8 lchip, uint16 serdes_id)
{
    /* anlt enabled when reset , SDK default cl73 disable when poweron*/
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_pcs_prbs_en(lchip, serdes_id, FALSE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_txclk_ready(lchip, serdes_id, TRUE));

    /* for sim, only care cdr lock */
    /*bit3 : monTxDetRxResult bit2 : monRxSigDetHf bit1 : monRxSigDetLowFreq bit0 : monRxCdrLock */
    CTC_ERROR_RETURN(_sys_tmg_serdes_mask_sigdet(lchip, serdes_id, 0xE));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_get_pll_cfg(uint8 lchip, uint16 macro_id, sys_tmg_serdes_pll_cfg_t* pll_cfg)
{
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 tbl_id   = 0;
    uint32 value    = 0;

    CTC_PTR_VALID_CHECK(pll_cfg)

    Hss32GPllCfg_m pll_cfg_t;

    tbl_id  = Hss32GPllCfg_t;

    cmd     = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(macro_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pll_cfg_t));

    DRV_IOR_FIELD(lchip, tbl_id, Hss32GPllCfg_hssPllCfg_0_cfgPllMulti_f, &value, &pll_cfg_t);
    pll_cfg->multi = value;
    DRV_IOR_FIELD(lchip, tbl_id, Hss32GPllCfg_hssPllCfg_0_cfgPllTxClkDiv_f, &value, &pll_cfg_t);
    pll_cfg->tx_clk_div = value;

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_speed_switch_proc(uint8 lchip, uint16 serdes_id, uint8 serdes_speed)
{
    uint16 macro_id      = 0;
    uint8 pll_violation = FALSE;
    uint8  txrx_speed   = 0;
    uint32 tmp_speed_value  = 0;
    uint8  tmp_speed_mode   = 0;
    uint8  old_pll_mult     = 0;
    uint8  old_pll_div      = 0;
    uint16 serdes_base = serdes_id / SYS_TMG_LANE_NUM_PER_HSS * SYS_TMG_LANE_NUM_PER_HSS;
    sys_tmg_serdes_pll_cfg_t pll_cfg = {0};

    char* speed_name[] = {
        "0G",
        "1.25G",
        "3.125G",
        "10.3125G",
        "11.40625G",
        "12.5G",
        "12.96875G",
        "10.9375G",
        "20.625G",
        "25.78125G",
        "28.125G",
        "26.5625G",
        "27.34375G",
        "27.78125G",
        "37.5G",
        "39.0625G",
        "51.5625G",
        "53.125G",
        "56.25G",
        "103.125G",
        "106.25G",
        "112.5G",
    };

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "// SERDES ID %d switch to speed %s\n", serdes_id, speed_name[serdes_speed]);

    macro_id    = SYS_TMG_GET_MAC_GROUP(serdes_id);

    CTC_ERROR_RETURN(_sys_tmg_serdes_get_pll_cfg(lchip, macro_id, &pll_cfg));
    txrx_speed = _sys_tmg_serdes_get_related_speed(serdes_speed);
    pll_violation = (pll_cfg.multi != g_pll_cfg_by_serdes_speed[Hss32GPll_cfgPllMulti][txrx_speed]) ? TRUE : FALSE;
    pll_violation = (pll_cfg.tx_clk_div != g_pll_cfg_by_serdes_speed[Hss32GPll_cfgPllTxClkDiv][txrx_speed])? TRUE : pll_violation;

    if(SERDES_SPEED_0G == serdes_speed)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_datapath_en(lchip, serdes_id, DMPS_RX, FALSE));
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_datapath_en(lchip, serdes_id, DMPS_TX, FALSE));
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_power(lchip, serdes_id, DMPS_RX, TMG_SERDES_RX_P1_STATE));
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_power(lchip, serdes_id, DMPS_TX, TMG_SERDES_TX_P1_STATE));
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, DMPS_TX, TRUE));
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, DMPS_RX, TRUE));
    }
    /*restriction : 11.40625G & 12.96875G & 27.78125G use different pll(default 4.6875G) , need reinitialize hss*/
    else if(pll_violation)
    {
        for(serdes_id = serdes_base; serdes_id < serdes_base + SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            CTC_ERROR_RETURN(sys_usw_dmps_db_get_serdes_speed(lchip, serdes_id, &tmp_speed_value));
            SYS_CONDITION_CONTINUE(tmp_speed_value == 0);
            /*all lane match PLL*/
            SYS_USW_SERDES_VALUE_2_SPEED(tmp_speed_value, tmp_speed_mode);
            txrx_speed = _sys_tmg_serdes_get_related_speed(tmp_speed_mode);
            SYS_CONDITION_RETURN(((old_pll_mult != 0) && (g_pll_cfg_by_serdes_speed[Hss32GPll_cfgPllMulti][txrx_speed] != old_pll_mult)), CTC_E_NONE);
            SYS_CONDITION_RETURN(((old_pll_div  != 0) && (g_pll_cfg_by_serdes_speed[Hss32GPll_cfgPllTxClkDiv][txrx_speed] != old_pll_div)), CTC_E_NONE);
            old_pll_mult = g_pll_cfg_by_serdes_speed[Hss32GPll_cfgPllMulti][txrx_speed];
            old_pll_div  = g_pll_cfg_by_serdes_speed[Hss32GPll_cfgPllTxClkDiv][txrx_speed];
        }

        CTC_ERROR_RETURN(_sys_tmg_serdes_set_wrapper_reset(lchip, macro_id, TRUE));
#ifdef TMG_SERDES_SIM

        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
#else
        sal_task_sleep(1);
#endif
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_wrapper_reset(lchip, macro_id, FALSE));
        CTC_ERROR_RETURN(_sys_tmg_serdes_poweron_per_macro(lchip, macro_id));
    }
    else
    {       
        CTC_ERROR_RETURN(_sys_tmg_serdes_poweron_per_lane(lchip, serdes_id));
    }

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_clear_anlt_intr(uint8 lchip, uint16 serdes_id)
{
    uint32 value    = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint8  txqm_id  = 0;
    uint8  txqm_lane_id     = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    ds_t   ds = {0};

    txqm_id         = SYS_TMG_GET_TXQM_BY_MAC_ID(serdes_id);
    txqm_lane_id    = SYS_TMG_GET_INNER_MAC_ID(serdes_id);

    /* clear anlt interrupt*/
    tbl_id = CtcPcsCtlInterruptFunc_t;
    dmps_CtcPcsCtlInterruptFunc_funcIntrHssL0Anlt_f(txqm_lane_id, fld_id);

    value = 1;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &value, &ds, txqm_id, 1);

    cmd     = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    index   = DRV_INS(txqm_id, 1);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

    /*clear inner state */
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_INT_STATUS_GOOD_CHECK), 1));
    CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_INT_STATUS_LT_TRAIN_OVER), 1));
    
    return CTC_E_NONE;
}


int32 _sys_tmg_serdes_poweron_per_lane(uint8 lchip, uint16 serdes_id)
{
    char* speed_name[] = {
        "0G",
        "1.25G",
        "3.125G",
        "10.3125G",
        "11.40625G",
        "12.5G",
        "12.96875G",
        "10.9375G",
        "20.625G",
        "25.78125G",
        "28.125G",
        "26.5625G",
        "27.34375G",
        "27.78125G",
        "37.5G",
        "39.0625G",
        "51.5625G",
        "53.125G",
        "56.25G",
        "103.125G",
        "106.25G",
        "112.5G",

    };

    sys_dmps_db_upt_info_t port_info = {0};
    uint32 speed_value;
    uint8  serdes_speed;

    CTC_ERROR_RETURN(_sys_tmg_serdes_pre_config_per_lane(lchip, serdes_id));

    CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
    DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PSD_SPEED);
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &port_info));
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PSD_SPEED,  speed_value);

    SYS_USW_SERDES_VALUE_2_SPEED(speed_value, serdes_speed);

    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "//SerDes Id %d power on %s\n", serdes_id, speed_name[serdes_speed]);

    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, DMPS_RX, 0));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, DMPS_TX, 0));
    CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_RX, 0));
    CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_TX, 0));

    CTC_ERROR_RETURN(_sys_tmg_serdes_cfg_tx(lchip, serdes_id, serdes_speed, FALSE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_cfg_rx(lchip, serdes_id, serdes_speed, FALSE));

    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_power(lchip, serdes_id, DMPS_RX, TMG_SERDES_RX_P0_STATE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_power(lchip, serdes_id, DMPS_TX, TMG_SERDES_TX_P0_STATE));

    /* TODO: rx data enable rely on sigdetlf*/
    /* txX_datapath enable needs asserted after 15 txclks*/
    sal_udelay(1);
#ifdef TMG_SERDES_SIM
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 15\n");
#endif
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_datapath_en(lchip, serdes_id, DMPS_TX, TRUE));
#ifdef TMG_SERDES_SIM
    //CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_lf_sigdet(lchip, serdes_id, TRUE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_datapath_en(lchip, serdes_id, DMPS_RX, TRUE));
#endif

    CTC_ERROR_RETURN(_sys_tmg_serdes_set_anlt_reset(lchip, serdes_id, DMPS_RX, FALSE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_anlt_reset(lchip, serdes_id, DMPS_TX, FALSE));

    //CTC_ERROR_RETURN(_sys_tmg_serdes_clear_anlt_intr(lchip, serdes_id));
    CTC_ERROR_RETURN(_sys_tmg_serdes_anlt_pre_config(lchip, serdes_id));

    return CTC_E_NONE;   
}

int32 _sys_tmg_serdes_poweron_per_hss(uint8 lchip, uint16 hss_id)
{
    uint8   lane_id      = 0;
    uint16  serdes_id    = 0;
    uint16  serdes_base  = SYS_TMG_LANE_NUM_PER_HSS * hss_id;
    uint16  serdes_mode[SYS_TMG_LANE_NUM_PER_HSS]  = {0};
    uint16  is_dyn[SYS_TMG_LANE_NUM_PER_HSS]  = {0};
    uint8   init_flag     = 0;

    sys_dmps_db_upt_info_t port_info = {0};

    /* check whether init hss */
    for(lane_id = 0; lane_id < SYS_TMG_LANE_NUM_PER_HSS; lane_id++)
    {
        serdes_id = serdes_base + lane_id;
        CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
        DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
        DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PORT_IF_MODE);
        DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PSD_IS_DYN);
        CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &port_info));
        DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PORT_IF_MODE, serdes_mode[lane_id]);
        DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PSD_IS_DYN, is_dyn[lane_id]);

        if(!SYS_TMG_IS_SERDES_ABANDON(serdes_mode[lane_id],is_dyn[lane_id]))
        {
            init_flag = TRUE;
        }
    }

    SYS_CONDITION_RETURN(!init_flag, CTC_E_NONE);

    /* wait sram bootloading */
    CTC_ERROR_RETURN(_sys_tmg_serdes_poll_sram_initdone(lchip, hss_id, 1));
    /* overwrite sram then assert ext_ld_done*/
    /*CTC_ERROR_RETURN(_sys_tmg_serdes_overwrite_firmware(lchip, hss_id));*/
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_sram_ext_lt_done(lchip, hss_id, TRUE));

    /* for fast sim, release reset all , in board move to lane level cfg*/
#ifdef TMG_SERDES_SIM
        for(serdes_id = serdes_base; serdes_id < serdes_base + SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            
        }
#endif

    /* lane level config */
    for(lane_id = 0; lane_id < SYS_TMG_LANE_NUM_PER_HSS; lane_id++)
    {
        SYS_CONDITION_CONTINUE(SYS_TMG_IS_SERDES_ABANDON(serdes_mode[lane_id],is_dyn[lane_id]));
        serdes_id = serdes_base + lane_id;

        CTC_ERROR_RETURN(_sys_tmg_serdes_poweron_per_lane(lchip, serdes_id));
    }

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_poweron_per_macro(uint8 lchip, uint16 macro_id)
{
    uint16 hss_id = 0;
    uint16 hss_id_start  = macro_id;
    uint16 hss_id_end    = hss_id_start + 1;
    uint16 serdes_base  = macro_id * SYS_TMG_LANE_NUM_PER_HSS;
    uint16 serdes_id    = 0;
    uint16 serdes_speed = 0;
    uint32 speed_value  = 0;

#ifdef TMG_SERDES_SIM
    _sys_tmg_serdes_load_internal_register(macro_id);
#endif

    /*find 1st used serdes speed to cfg pll*/
    for(serdes_id = serdes_base; serdes_id < serdes_base + SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
    {
        CTC_ERROR_RETURN(sys_usw_dmps_db_get_serdes_speed(lchip, serdes_base, &speed_value));
        SYS_USW_SERDES_VALUE_2_SPEED(speed_value, serdes_speed);
        SYS_CONDITION_BREAK(serdes_speed != SERDES_SPEED_0G);
    }

    CTC_ERROR_RETURN(_sys_tmg_serdes_cfg_pll(lchip, macro_id, TMG_SERDES_PLLA, serdes_speed));
    CTC_ERROR_RETURN(_sys_tmg_serdes_cfg_com(lchip, macro_id));
    /* todo: check lane level ack*/
    for(serdes_id = serdes_base; serdes_id < serdes_base + SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_RX, 1));
        CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_TX, 1));
    }
/*external ref CANT verify in sim env, KEEP SAME AS ASIC*/
    CTC_ERROR_RETURN(_sys_tmg_serdes_ref_clk_sel(lchip, macro_id, TMG_SERDES_REF_ALT0_CLK));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_ref_clk_en(lchip, macro_id, TMG_SERDES_REFA, TRUE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_ref_clk_en(lchip, macro_id, TMG_SERDES_REFB, TRUE));

#ifdef TMG_SERDES_SIM
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
#endif

    CTC_ERROR_RETURN(_sys_tmg_serdes_set_phy_reset(lchip, macro_id, FALSE));
    CTC_ERROR_RETURN(_sys_tmg_serdes_set_cr_reset(lchip, macro_id, FALSE));

    for(hss_id = hss_id_start; hss_id < hss_id_end; hss_id++)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_poweron_per_hss(lchip, hss_id));
    }

    return CTC_E_NONE;
}

#ifdef TMG_SERDES_SIM
extern int32
_sys_tmg_mac_set_mac_en(uint8 lchip, uint16 lport, void* p_port_info, uint8 enable, uint8 db_upt_flag);

int32 _sys_tmg_serdes_poll_reg(uint8 lchip, uint16 hss_id, uint16 reg)
{
    uint32 index    = 0;
    uint32 cmd      = 0;
    uint32 value    = 0;
    uint8  macro_id = 0;
    uint8  acc_id   = 0;

    uint32 mon_addr[SYS_TMG_MAX_HSS_NUM + 1] = {0x60248980, 0x60248b80, 0x602c8980, 0x602c8b80, 0x60348980, 0x60348b80,
                                                0x603c8980, 0x603c8b80, 0x60448980, 0x60448b80, 0x68248980, 0x68248b80,
                                                0x682c8980, 0x682c8b80, 0x68348980, 0x68348b80, 0x683c8980, 0x683c8b80,
                                                0x68448980, 0x68448b80, 0x51cd6580};

    Hss32GRegAccCtl_m       acc_ctl;

    macro_id = hss_id;
    acc_id   = 0;

    index = DRV_INS(macro_id, 0);
    cmd   = DRV_IOR(Hss32GRegAccCtl_t, DRV_ENTRY_FLAG);

    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_ctl));

    /* operate read*/
    value = acc_id;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccId_f, &value, &acc_ctl, macro_id, 0);
    value = reg;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccAddr_f, &value, &acc_ctl, macro_id, 0);
    value = 1;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccIsRead_f, &value, &acc_ctl, macro_id, 0);
    value = 1;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccCtl_t, Hss32GRegAccCtl_hssAccValid_f, &value, &acc_ctl, macro_id, 0);

    cmd   = DRV_IOW(Hss32GRegAccCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_ctl));


    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", mon_addr[macro_id], 0x80000000, 0x80000000, 1000000000);
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");

    /*set cr invalid*/
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "write chip 0 tbl-reg  Hss32GRegAccCtl.%d  0  field hssAccValid 0\n", hss_id);


    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_poll_lt_fail(uint8 lchip, uint16 serdes_id)
{
    uint8  macro_id = 0;
    uint8  txqm_id  = 0;
    uint8  txqm_lane_id     = 0;
    uint8  macro_lane_id    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    char   fld_str[64] = {0};

    uint32 lt_mon_addr[] =  {0x6024898c, 0x60248b8c, 0x602c898c, 0x602c8b8c, 0x6034898c, 0x60348b8c, 0x603c898c, 0x603c8b8c, 0x6044898c, 0x60448b8c, 0x6824898c, 0x68248b8c, 0x682c898c, 0x682c8b8c, 0x6834898c, 0x68348b8c, 0x683c898c, 0x683c8b8c, 0x6844898c, 0x68448b8c, 0x5444258c};
    txqm_id         = SYS_TMG_GET_TXQM_BY_MAC_ID(serdes_id);
    txqm_lane_id    = SYS_TMG_GET_INNER_MAC_ID(serdes_id);
    macro_id        = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    macro_lane_id   = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);
                              
    /*wait lt timeout*/
    tbl_id = Hss32GLtMon_t;
    dmps_Hss32GLtMon_hssLtMon_0_monLtFail_f(macro_lane_id, fld_id);

    drv_usw_get_field_string_by_id(lchip, tbl_id, fld_id, fld_str);
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp,"// #polling  %-20s 0 inst %-5d entry 0 field %-20s exp_value %d\n", \
                    TABLE_NAME(lchip, tbl_id), txqm_id, fld_str, 1<< (8*macro_lane_id+2)); \
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", lt_mon_addr[macro_id], 1<< (8*macro_lane_id+2), 1<< (8*macro_lane_id+2), 1000000000);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_poll_rx_valid(uint8 lchip, uint16 serdes_id)
{
    uint8  macro_id = 0;
    uint8  txqm_id  = 0;
    uint8  txqm_lane_id     = 0;
    uint8  macro_lane_id    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    char   fld_str[64] = {0};

    uint32 rx_mon_addr[] = {0x60248910, 0x60248b10, 0x602c8910, 0x602c8b10, 0x60348910, 0x60348b10, 0x603c8910, 0x603c8b10, 0x60448910, 0x60448b10, 0x68248910, 0x68248b10, 0x682c8910, 0x682c8b10, 0x68348910, 0x68348b10, 0x683c8910, 0x683c8b10, 0x68448910, 0x68448b10, 0x54442510};

    txqm_id         = SYS_TMG_GET_TXQM_BY_MAC_ID(serdes_id);
    txqm_lane_id    = SYS_TMG_GET_INNER_MAC_ID(serdes_id);
    macro_id        = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    macro_lane_id   = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);
    
    /*wait lt timeout*/
    tbl_id = Hss32GRxMon_t;
    dmps_Hss32GRxMon_hssRxMon_0_monRxCdrLock_f(macro_lane_id, fld_id);

    drv_usw_get_field_string_by_id(lchip, tbl_id, fld_id, fld_str);
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp,"// #polling  %-20s 0 inst %-5d entry 0 field %-20s exp_value %d\n", \
                    TABLE_NAME(lchip, tbl_id), macro_id, fld_str, 1<<0); \
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", rx_mon_addr[macro_id] + 4 * macro_lane_id, 1<<0, 1<<0, 1000000000);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_poll_sigdet_lf(uint8 lchip, uint16 serdes_id)
{
    uint8  macro_id = 0;
    uint8  txqm_id  = 0;
    uint8  txqm_lane_id     = 0;
    uint8  macro_lane_id    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    char   fld_str[64] = {0};

    uint32 rx_mon_addr[] = {0x60248910, 0x60248b10, 0x602c8910, 0x602c8b10, 0x60348910, 0x60348b10, 0x603c8910, 0x603c8b10, 0x60448910, 0x60448b10, 0x68248910, 0x68248b10, 0x682c8910, 0x682c8b10, 0x68348910, 0x68348b10, 0x683c8910, 0x683c8b10, 0x68448910, 0x68448b10, 0x54442510};

    txqm_id         = SYS_TMG_GET_TXQM_BY_MAC_ID(serdes_id);
    txqm_lane_id    = SYS_TMG_GET_INNER_MAC_ID(serdes_id);
    macro_id        = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    macro_lane_id   = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);
    
    tbl_id = Hss32GRxMon_t;
    dmps_Hss32GRxMon_hssRxMon_0_monRxSigdetLowFreq_f(macro_lane_id, fld_id);

    drv_usw_get_field_string_by_id(lchip, tbl_id, fld_id, fld_str);
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp,"// #polling  %-20s 0 inst %-5d entry 0 field %-20s exp_value %d\n", \
                    TABLE_NAME(lchip, tbl_id), macro_id, fld_str, 1<<1); \
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", rx_mon_addr[macro_id] + 4 * macro_lane_id, 1<<1, 1<<1, 1000000000);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_poll_adapt_ack(uint8 lchip, uint16 serdes_id)
{
    uint8  macro_id = 0;
    uint8  txqm_id  = 0;
    uint8  txqm_lane_id     = 0;
    uint8  macro_lane_id    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    char   fld_str[64] = {0};

    uint32 rx_mon_addr[] = {0x60248910, 0x60248b10, 0x602c8910, 0x602c8b10, 0x60348910, 0x60348b10, 0x603c8910, 0x603c8b10, 0x60448910, 0x60448b10, 0x68248910, 0x68248b10, 0x682c8910, 0x682c8b10, 0x68348910, 0x68348b10, 0x683c8910, 0x683c8b10, 0x68448910, 0x68448b10, 0x54442510};

    txqm_id         = SYS_TMG_GET_TXQM_BY_MAC_ID(serdes_id);
    txqm_lane_id    = SYS_TMG_GET_INNER_MAC_ID(serdes_id);
    macro_id        = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    macro_lane_id   = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);
    
    tbl_id = Hss32GRxMon_t;
    dmps_Hss32GRxMon_hssRxMon_0_monRxAdaptAck_f(macro_lane_id, fld_id);

    drv_usw_get_field_string_by_id(lchip, tbl_id, fld_id, fld_str);
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp,"// #polling  %-20s 0 inst %-5d entry 0 field %-20s exp_value %d\n", \
                    TABLE_NAME(lchip, tbl_id), macro_id, fld_str, 1<<30); \
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", rx_mon_addr[macro_id] + 4 * macro_lane_id, 1<<30, 1<<30, 1000000000);

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_clear_acc_ack(uint8 lchip, uint16 hss_id)
{
    uint32 index    = 0;
    uint32 cmd      = 0;
    uint32 value    = 0;
    uint8  macro_id = 0;
    uint8  acc_id   = 0;
    Hss32GRegAccResult_m    acc_mon;

    macro_id = hss_id;
    acc_id   = 0;
    index = DRV_INS(macro_id, 0);

    /*clear ack*/
    cmd = DRV_IOR(Hss32GRegAccResult_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_mon));

    value = 0;
    DRV_IOW_FIELD_NZ(lchip, Hss32GRegAccResult_t, Hss32GRegAccResult_hssAccAck_f, &value, &acc_mon, macro_id, 0);
    cmd = DRV_IOW(Hss32GRegAccResult_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &acc_mon));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_poll_reg_field(uint8 lchip, uint16 serdes_id, _sys_tmg_serdes_field_t* p_field_info)
{
    uint16 reg = 0;
    uint8  hss_id  = 0;

    hss_id = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);

    TMG_SERDES_GET_ADDRESS(p_field_info->type, serdes_id, p_field_info->offset, reg);
    CTC_ERROR_RETURN(_sys_tmg_serdes_poll_reg(lchip, hss_id, reg));

    return CTC_E_NONE;
}

/// TODO
int32 _sys_tmg_serdes_poll_anlt_intr(uint8 lchip, uint16 serdes_id, uint8 type)
{
    uint8  macro_id = 0;
    uint8  txqm_id  = 0;
    uint8  txqm_lane_id     = 0;
    uint8  macro_lane_id    = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    char   fld_str[64] = {0};

    uint32 pcs_intr_addr[] = {0x60248e50, 0x602c8e50, 0x60348e50, 0x603c8e50, 0x60448e50, 0x68248e50, 0x682c8e50, 0x68348e50, 0x683c8e50, 0x68448e50};
    uint32 acc_mon_addr [] = {0x60248980, 0x60248b80, 0x602c8980, 0x602c8b80, 0x60348980, 0x60348b80, 0x603c8980,
                              0x603c8b80, 0x60448980, 0x60448b80, 0x68248980, 0x68248b80, 0x682c8980, 0x682c8b80,
                              0x68348980, 0x68348b80, 0x683c8980, 0x683c8b80, 0x68448980, 0x68448b80, 0x54442580};

    txqm_id         = SYS_TMG_GET_TXQM_BY_MAC_ID(serdes_id);
    txqm_lane_id    = SYS_TMG_GET_INNER_MAC_ID(serdes_id);
    macro_id        = SYS_TMG_GET_HSS_ID_BY_SERDES(serdes_id);
    macro_lane_id   = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);
                              
    /* poll anlt interrupt*/
    tbl_id = CtcPcsCtlInterruptFunc_t;
    dmps_CtcPcsCtlInterruptFunc_funcIntrHssL0Anlt_f(txqm_lane_id, fld_id);

    drv_usw_get_field_string_by_id(lchip, tbl_id, fld_id, fld_str);
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp,"// #polling  %-20s 0 inst %-5d entry 0 field %-20s exp_value %d\n", \
                    TABLE_NAME(lchip, tbl_id), txqm_id, fld_str, 1); \
    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", pcs_intr_addr[txqm_id], 1<<txqm_lane_id, 1<<txqm_lane_id, 1000000000);


    if(type == 0)
    {
        //CTC_ERROR_RETURN(_sys_tmg_serdes_poll_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_INT_STATUS_AN_INC_LINK)));
        CTC_ERROR_RETURN(_sys_tmg_serdes_poll_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_INT_STATUS_GOOD_CHECK)));
        
        tbl_id = Hss32GRegAccResult_t;
        fld_id = Hss32GRegAccResult_hssAccAckData_f;

        drv_usw_get_field_string_by_id(lchip, tbl_id, fld_id, fld_str);
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp,"// #polling  %-20s 0 inst %-5d entry 0 field %-20s exp_value %d\n", \
                        TABLE_NAME(lchip, tbl_id), macro_id, fld_str, 1<<7); \
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", acc_mon_addr[macro_id], 1<<7, 1<<7, 1000000000);

/* for an incompatiable link */
#if 0
        drv_usw_get_field_string_by_id(lchip, tbl_id, fld_id, fld_str);
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp,"// #polling  %-20s 0 inst %-5d entry 0 field %-20s exp_value %d\n", \
                        TABLE_NAME(lchip, tbl_id), macro_id, fld_str, 1<<7); \
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", acc_mon_addr[macro_id], 1<<1, 1<<1, 1000000000);
#endif

        CTC_ERROR_RETURN(_sys_tmg_serdes_clear_acc_ack(lchip, macro_id));

    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_poll_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_INT_STATUS_LT_TRAIN_OVER)));
        
        tbl_id = Hss32GRegAccResult_t;
        fld_id = Hss32GRegAccResult_hssAccAckData_f;

        drv_usw_get_field_string_by_id(lchip, tbl_id, fld_id, fld_str);
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp,"// #polling  %-20s 0 inst %-5d entry 0 field %-20s exp_value %d\n", \
                        TABLE_NAME(lchip, tbl_id), macro_id, fld_str, 1<<0); \
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "until_mask %08x %08x %08x %0d \n", acc_mon_addr[macro_id], 1<<0, 1<<0, 1000000000);
        
        CTC_ERROR_RETURN(_sys_tmg_serdes_clear_acc_ack(lchip, macro_id));
    }


    CTC_ERROR_RETURN(_sys_tmg_serdes_clear_anlt_intr(lchip, serdes_id));

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_test_anlt(uint8 lchip, uint16 macro_id, uint8 case_type)
{
    uint16 serdes_id = 0;
    uint16 dport    = 0;
    uint16 times = 0;
    sys_dmps_db_upt_info_t   upt_info = {0};
    sys_port_api_dmps_info_t info = {0}; 
    ctc_chip_serdes_info_t   serdes_info = {0};
    uint8   lane_id = 0;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    switch(case_type)
    {
        case 0:
            /*case 0 normal anlt case*/
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 0));                
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, FALSE));
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 1));
                 CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
                 DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
                 CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
                 DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
                 /*assume dport = lport*/
                 CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
                 CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
            }
            
            break;
        case 1:
            /*case 1 restart an for multiple times*/
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                for(times = 100; times > 0; times--)
                {
                    CTC_ERROR_RETURN(_sys_tmg_serdes_clear_anlt_intr(lchip, serdes_id));
                    CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, TRUE));
                    if(times > 1)
                    {
                        CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, FALSE));
                    }
                }           
            }
            
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 0));
                CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, FALSE));
                CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, TRUE));
                CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 1));
                CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
                DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
                CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
                DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
                /*assume dport = lport*/
                CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
                CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
            }
            break;
        case 2:
            /*case 2 restart anlt when lt processing */
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 0));                
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, TRUE));
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, FALSE));
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, FALSE));
                 CTC_ERROR_RETURN(_sys_tmg_serdes_clear_anlt_intr(lchip, serdes_id));
            }

            /*recover step: toggle reset*/
            /*
            1.toggle LT soft reset , keep assert in sim at least wait for 200ns 
            2.toggle rxX_reset , need keep assert for at least 10 ref clock
            3.wait for rxX_ack set to 0 
            4.restart LT
            */
            
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 lane_id = SYS_TMG_GET_INNER_LANE_BY_SERDES(serdes_id);
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_anlt_reset(lchip, serdes_id, DMPS_RX, 1));
                 SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_anlt_reset(lchip, serdes_id, DMPS_RX, 0));
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, DMPS_RX, 1)); 
                 SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, DMPS_RX, 0)); 
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_RX, 0)); 
            }
            /*end of recover step*/

            /*due to soft reset, reconfig anlt pre config*/
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                CTC_ERROR_RETURN(_sys_tmg_serdes_anlt_pre_config(lchip, serdes_id));
            }
            
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 0));                
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 1));
                 CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
                 DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
                 CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
                 DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
                 /*assume dport = lport*/
                 CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
                 CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
            }
            break;
        case 3:
            /*case 3 restart lt for multiple times */
            for(times = 100; times > 0; times--)
            {
                for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
                {
                    if(times > 1)
                    {
                        CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, FALSE));
                        CTC_ERROR_RETURN(_sys_tmg_serdes_clear_anlt_intr(lchip, serdes_id));

                    }
                    CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, TRUE));
                }           
            }
            
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 1));
                CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
                DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
                CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
                DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
                /*assume dport = lport*/
                CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
                CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
            }
            break;
        case 4:
            /*case 4 switch 4x25g to 4x10g*/
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, TRUE));
            }

            CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, 0, 0));                
            for(serdes_id = 0; serdes_id < SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, FALSE));

            }                        
            /*switch 4x25g to 4x10g*/
            serdes_info.serdes_mode        = CTC_CHIP_SERDES_XLG_MODE;
            serdes_info.overclocking_speed = CTC_CHIP_SERDES_OCS_MODE_NONE;
            serdes_info.serdes_id = 0;
            CTC_ERROR_RETURN(_sys_usw_port_api_set_serdes_mode(lchip, &serdes_info));
            /*enable lane 0-3 lt*/
            for(serdes_id = 0; serdes_id < SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, TRUE));
            }

            
            CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, SYS_TMG_LANE_NUM_PER_HSS, 0));                
            for(serdes_id = SYS_TMG_LANE_NUM_PER_HSS; serdes_id <  2*SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, FALSE));

            }                        
            /*switch 4x25g to 4x10g*/
            serdes_info.serdes_mode        = CTC_CHIP_SERDES_XLG_MODE;
            serdes_info.overclocking_speed = CTC_CHIP_SERDES_OCS_MODE_NONE;
            serdes_info.serdes_id = SYS_TMG_LANE_NUM_PER_HSS;
            CTC_ERROR_RETURN(_sys_usw_port_api_set_serdes_mode(lchip, &serdes_info));
            /*enable lane 0-3 lt*/
            for(serdes_id = SYS_TMG_LANE_NUM_PER_HSS; serdes_id <  2*SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, TRUE));
            }


            /*wait lane 0-3 lt ok*/
            for(serdes_id = 0; serdes_id < SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 1));
            }
            
            CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
            DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, 0);
            CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
            DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
            CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
            CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));

            /*wait lane 4-7 lt ok*/
            
            for(serdes_id = SYS_TMG_LANE_NUM_PER_HSS; serdes_id <  2*SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 1));
            }
            
            CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
            DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, SYS_TMG_LANE_NUM_PER_HSS);
            CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
            DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
            CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
            CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
            
            break;

        case 5:
            /*case 5 for debug,  restart anlt when lt processed */
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 0));                
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, TRUE));

            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                /*wait lt done*/
                CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 1));                              
                CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, FALSE));
                CTC_ERROR_RETURN(_sys_tmg_serdes_clear_anlt_intr(lchip, serdes_id));           
            }
           
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_RESTART), 1));
                 CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_RESTART), 0));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 0));                
                 CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_ENABLE), TRUE));
                 CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RESTART), TRUE));
                 CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RESTART), FALSE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 1));
                 CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
                 DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
                 CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
                 DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
                 /*assume dport = lport*/
                 CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
                 CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
            }
            break;
            case 6:
            /*restart an when lt train fail*/
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < (macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 0));                
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < (macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                /*wait lt fail*/
                CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lt_fail(lchip, serdes_id));                              
                CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, FALSE));
                CTC_ERROR_RETURN(_sys_tmg_serdes_clear_anlt_intr(lchip, serdes_id));           
            }
           
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_RESTART), 1));
                 CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_AN_RESTART), 0));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 0));                
                 CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_ENABLE), TRUE));
                 CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RESTART), TRUE));
                 CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_LT_RESTART), FALSE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 1));
                 CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
                 DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
                 CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
                 DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
                 /*assume dport = lport*/
                 CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
                 CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
            }
            break;
            case 7:
            /*close anlt after lt done,  then restart anlt*/
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 0));                
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                /*wait lt ok*/
                CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 1));                
                CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, FALSE));
                CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, FALSE));
                CTC_ERROR_RETURN(_sys_tmg_serdes_clear_anlt_intr(lchip, serdes_id));           
            }
           
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 0));                
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 1));
                 CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
                 DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
                 CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
                 DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
                 /*assume dport = lport*/
                 CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
                 CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
            }

            break;
            case 8:
            /*case 8 back to Force Mode*/
            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 0));                
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, TRUE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_poll_anlt_intr(lchip, serdes_id, 1));
                 CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
                 DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
                 CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
                 DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
                 /*assume dport = lport*/
                 CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
                 CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
                 SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
                 CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, FALSE, TRUE));
            }    

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_tx_train_en(lchip, serdes_id, FALSE));
                 CTC_ERROR_RETURN(_sys_tmg_serdes_set_serdes_auto_neg_en(lchip, serdes_id, FALSE));
            }

            for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
            {
                 CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
                 DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
                 CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
                 DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
                 /*assume dport = lport*/
                 CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
                 CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
            }

            break;
        }
    
    return CTC_E_NONE;

}

int32 _sys_tmg_serdes_test_prbs(uint8 lchip, uint16 macro_id)
{
    uint16 value = 0;
    uint16 serdes_id;
    uint8  pattern;
    uint32  insert_bit = 0;
    
    DP_DEBUG_FUNCTION_CALLED_PRINT();

    /* case 1 : test resync */
    for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
    {
        /*step 1. set prbs rx pattern*/
        CTC_ERROR_RETURN(_sys_tmg_serdes_prbs_type2pattern(CTC_CHIP_SERDES_PRBS31_PLUS, &pattern));
        value = pattern;
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_TX_PRBS_MODE), value));       
        CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_RX_PRBS_MODE), value));
    }

    for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
    {
        /*step 2. reset prbs counter*/
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_prbs_cnt_rst(lchip, serdes_id));
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 2000\n");
    }

    for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
    {
        for(insert_bit = 125; insert_bit > 0; insert_bit--)
        {
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_PRBS_TRIGGER_ERR), 1));
        }
    }


    for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_poll_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_PRBS_OV14)));
        CTC_ERROR_RETURN(_sys_tmg_serdes_poll_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_PRBS_COUNT)));
    }

    
    for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
    {
        /*step 2. reset prbs counter*/
        CTC_ERROR_RETURN(_sys_tmg_serdes_set_prbs_cnt_rst(lchip, serdes_id));
        SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 2000\n");
    }
    
    for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
    {
        for(insert_bit = 256; insert_bit > 0; insert_bit--)
        {
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_PRBS_TRIGGER_ERR), 1));
        }
    }
    
    for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
    {
        CTC_ERROR_RETURN(_sys_tmg_serdes_poll_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_PRBS_OV14)));
        CTC_ERROR_RETURN(_sys_tmg_serdes_poll_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_PRBS_COUNT)));
    }


    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

int32 _sys_tmg_serdes_test_adapt(uint8 lchip, uint16 macro_id, uint16 case_type)
{
    uint16 serdes_id = 0;
    uint16 lp_serdes_id = 0;
    uint16 dport    = 0;
    uint16 times = 0;
    sys_dmps_db_upt_info_t   upt_info = {0};
    sys_port_api_dmps_info_t info = {0};

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    switch(case_type)
    {
        case 1:
        /* case 1 : test de-assert rxX_adapt_req when adapt waiting done*/   

        for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
            DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
            CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
            DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
            /*assume dport = lport*/
            CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
            CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
        }
        
        for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            for(times = 20; times > 0; times--)
            {
                CTC_ERROR_RETURN(_sys_tmg_serdes_set_rx_train_en(lchip, serdes_id, TRUE)); 
                
                if(times)
                {
                    
                    SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
                    CTC_ERROR_RETURN(_sys_tmg_serdes_set_rx_train_en(lchip, serdes_id, FALSE));        
                }    
            }
        }
        break;
        case 2:
        /* case 2 : local cdr loss of lock when adapting */
        for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
            DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
            CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
            DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
            /*assume dport = lport*/
            CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
            CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
        }

        for(serdes_id = macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < (macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_rx_train_en(lchip, serdes_id, TRUE));
            lp_serdes_id = serdes_id + SYS_TMG_LANE_NUM_PER_HSS;
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_datapath_en(lchip, lp_serdes_id, DMPS_TX, FALSE));           
            SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 20000\n");           
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_datapath_en(lchip, lp_serdes_id, DMPS_TX, TRUE));           
        }
        break;
        case 3:
        /*AkroStar Suggested Process*/
        for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
            DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
            CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
            DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
            /*assume dport = lport*/
            CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
            CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
        }
        
        for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            CTC_ERROR_RETURN(_sys_tmg_serdes_poll_rx_valid(lchip, serdes_id));
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_datapath_en(lchip, serdes_id, DMPS_RX, FALSE));
            /*Assert rxX_adapt_in_prog to the PHY, already configed poweron*/
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, DMPS_RX, TRUE));
            SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");           
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, DMPS_RX, FALSE));           
            CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_RX, 0));
            CTC_ERROR_RETURN(_sys_tmg_serdes_poll_sigdet_lf(lchip, serdes_id));
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_datapath_en(lchip, serdes_id, DMPS_RX, TRUE));
            CTC_ERROR_RETURN(_sys_tmg_serdes_poll_rx_valid(lchip, serdes_id));
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_rx_train_en(lchip, serdes_id, TRUE));
            CTC_ERROR_RETURN(_sys_tmg_serdes_poll_adapt_ack(lchip, serdes_id));
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_rx_train_en(lchip, serdes_id, FALSE));
        }
        break;
        case 4:
        /*keep rxX_adapt_in_prog 1, toggle rxX_reset, check written reg is keep ?*/
        for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            CTC_ERROR_RETURN(_sys_tmg_serdes_write_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_TAP1_ADPT_VAL), serdes_id));
        }        

        for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
             CTC_ERROR_RETURN(_sys_tmg_serdes_set_anlt_reset(lchip, serdes_id, DMPS_RX, 1));
             SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
             CTC_ERROR_RETURN(_sys_tmg_serdes_set_anlt_reset(lchip, serdes_id, DMPS_RX, 0));
             CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, DMPS_RX, 1)); 
             SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
             CTC_ERROR_RETURN(_sys_tmg_serdes_set_lane_reset(lchip, serdes_id, DMPS_RX, 0)); 
             CTC_ERROR_RETURN(_sys_tmg_serdes_poll_lane_ack(lchip, serdes_id, DMPS_RX, 0)); 
        }

        for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            CTC_ERROR_RETURN(_sys_tmg_serdes_poll_reg_field(lchip, serdes_id, REG_STR(TMG_SERDES_DFE_TAP1_ADPT_VAL)));
        }        
        break;

        case 5:
        /*toggle rxX_data_en to check whether coarse_adpt_done_flag will down*/
        for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &upt_info));
            DMPS_DB_SET_MAP_INFO(upt_info, DMPS_DB_PHYSIC_SERDES, serdes_id);
            CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &upt_info));
            DMPS_DB_GET_MAP_INFO(upt_info, DMPS_DB_DPORT, dport);
            /*assume dport = lport*/
            CTC_ERROR_RETURN(sys_usw_dmps_db_api_get_port_info(lchip, dport, &info));
            CTC_ERROR_RETURN(_sys_tmg_mac_set_mac_en(lchip, dport, (void *)&info, TRUE, TRUE));
        }

        for(serdes_id = 2* macro_id * SYS_TMG_LANE_NUM_PER_HSS; serdes_id < 2*(macro_id+1) * SYS_TMG_LANE_NUM_PER_HSS; serdes_id++)
        {
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_datapath_en(lchip, serdes_id, DMPS_RX, FALSE));   
            SYS_DMPS_DUMP_PRINT(g_tm_dump_fp, "sleep 200\n");
            CTC_ERROR_RETURN(_sys_tmg_serdes_set_datapath_en(lchip, serdes_id, DMPS_RX, TRUE));   
        }
        break;
        
    }
    

    return CTC_E_NONE;
}

#endif

int32 sys_tmg_serdes_init(uint8 lchip)
{
#if  defined(EMULATION_ENV) && !defined(TMG_SERDES_SIM)
    return CTC_E_NONE;
#endif
    uint16 macro_id = 0;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    g_print_tbl = 1;

#ifdef EMULATION_ENV
    for(macro_id = 4; macro_id < 8; macro_id++)
#else
    for(macro_id = 0; macro_id < SYS_TMG_MAC_GROUP_NUM; macro_id++)
#endif
    {
        /*for sim dump macro 0 & 1 */
#ifdef TMG_SERDES_SIM
        //if(macro_id !=0 && macro_id != 1)
        if(macro_id !=20)
        //if(!(macro_id >= 32/4 && macro_id <= 39/4) && !(macro_id >= 72/4 && macro_id <= 79/4) )
        //if(macro_id >= 20)
        {
            continue;
        }
#endif

        CTC_ERROR_RETURN(sys_usw_dmps_serdes_set_group_init(lchip, macro_id));    

    }

    g_print_tbl = 0;

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

int32
sys_tmg_serdes_set_property(uint8 lchip, ctc_chip_property_t chip_prop, void* p_value)
{   
    return CTC_E_NONE;
}

int32
sys_tmg_serdes_get_property(uint8 lchip, ctc_chip_property_t chip_prop, void* p_value)
{

    return CTC_E_NONE;
}

int32
_sys_tmg_serdes_dump(uint8 lchip, uint16 serdes_id)
{
    
    return CTC_E_NONE;
}
